为什么在 asio 的示例中 tcp 接受器模式使用 shared_pointer 模型包装堆套接字,而 udp 使用堆栈套接字?
Why in asio's example the tcp acceptor pattern uses shared_pointer model wrapping heap socket, while udp use stack socket?
源代码:
https://think-async.com/Asio/asio-1.18.0/doc/asio/tutorial/tutdaytime7/src.html
tcp_server 显示在堆上使用套接字的意图,由称为 tcp_connection.
的类型包装
class tcp_server
{
private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(io_context_);
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
asio::placeholders::error));
}
void handle_accept(tcp_connection::pointer new_connection,
const asio::error_code& error)
{
if (!error)
{
new_connection->start();
}
start_accept();
}
...
套接字堆对象由 enable_shared_from_this
aka shared_ptr
管理
class tcp_connection
: public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(asio::io_context& io_context)
{
return pointer(new tcp_connection(io_context));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
message_ = make_daytime_string();
asio::async_write(socket_, asio::buffer(message_),
boost::bind(&tcp_connection::handle_write, shared_from_this()));
}
...
而udp服务器只使用成员套接字。
class udp_server
{
public:
udp_server(asio::io_context& io_context)
: socket_(io_context, udp::endpoint(udp::v4(), 13))
{
start_receive();
}
private:
void start_receive()
{
socket_.async_receive_from(
asio::buffer(recv_buffer_), remote_endpoint_,
boost::bind(&udp_server::handle_receive, this,
asio::placeholders::error));
}
void handle_receive(const asio::error_code& error)
{
if (!error)
{
boost::shared_ptr<std::string> message(
new std::string(make_daytime_string()));
socket_.async_send_to(asio::buffer(*message), remote_endpoint_,
boost::bind(&udp_server::handle_send, this, message));
start_receive();
}
}
void handle_send(boost::shared_ptr<std::string> /*message*/)
{
}
udp::socket socket_;
udp::endpoint remote_endpoint_;
boost::array<char, 1> recv_buffer_;
};
我的问题是为什么 tcp 接受器和 udp 套接字示例选择不同的方法?
只是为了展示不同的方法...
因此,考虑到上下文,您可以使用一种或另一种解决方案。
共享指针用于管理连接的生命周期。
在 TCP 的情况下,拥有多个连接更为常见,这会导致您可能拥有多个生命周期不相关的连接实例。
UDP 是无连接的,很多时候用于一次性消息。
事实上,您可以想出将共享指针与 UDP 一起使用的场景(例如,“逻辑连接”,例如通过 UDP 传输音频流)。
另外,反过来你可以用不同的方式解决生命难题(不管 TCP/UDP)。例如,我在这里使用了 std::list
(为了参考稳定性)明智的单线程访问: ¹
¹ 我之前将其与此答案中的 shared_ptr 方法进行了比较:,您可能也会感兴趣
源代码: https://think-async.com/Asio/asio-1.18.0/doc/asio/tutorial/tutdaytime7/src.html
tcp_server 显示在堆上使用套接字的意图,由称为 tcp_connection.
的类型包装class tcp_server
{
private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(io_context_);
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
asio::placeholders::error));
}
void handle_accept(tcp_connection::pointer new_connection,
const asio::error_code& error)
{
if (!error)
{
new_connection->start();
}
start_accept();
}
...
套接字堆对象由 enable_shared_from_this
aka shared_ptr
class tcp_connection
: public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(asio::io_context& io_context)
{
return pointer(new tcp_connection(io_context));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
message_ = make_daytime_string();
asio::async_write(socket_, asio::buffer(message_),
boost::bind(&tcp_connection::handle_write, shared_from_this()));
}
...
而udp服务器只使用成员套接字。
class udp_server
{
public:
udp_server(asio::io_context& io_context)
: socket_(io_context, udp::endpoint(udp::v4(), 13))
{
start_receive();
}
private:
void start_receive()
{
socket_.async_receive_from(
asio::buffer(recv_buffer_), remote_endpoint_,
boost::bind(&udp_server::handle_receive, this,
asio::placeholders::error));
}
void handle_receive(const asio::error_code& error)
{
if (!error)
{
boost::shared_ptr<std::string> message(
new std::string(make_daytime_string()));
socket_.async_send_to(asio::buffer(*message), remote_endpoint_,
boost::bind(&udp_server::handle_send, this, message));
start_receive();
}
}
void handle_send(boost::shared_ptr<std::string> /*message*/)
{
}
udp::socket socket_;
udp::endpoint remote_endpoint_;
boost::array<char, 1> recv_buffer_;
};
我的问题是为什么 tcp 接受器和 udp 套接字示例选择不同的方法?
只是为了展示不同的方法...
因此,考虑到上下文,您可以使用一种或另一种解决方案。
共享指针用于管理连接的生命周期。
在 TCP 的情况下,拥有多个连接更为常见,这会导致您可能拥有多个生命周期不相关的连接实例。
UDP 是无连接的,很多时候用于一次性消息。
事实上,您可以想出将共享指针与 UDP 一起使用的场景(例如,“逻辑连接”,例如通过 UDP 传输音频流)。
另外,反过来你可以用不同的方式解决生命难题(不管 TCP/UDP)。例如,我在这里使用了 std::list
(为了参考稳定性)明智的单线程访问:
¹ 我之前将其与此答案中的 shared_ptr 方法进行了比较: