为啥这个 boost::asio::tcp::socket 可以重用?
Posted
技术标签:
【中文标题】为啥这个 boost::asio::tcp::socket 可以重用?【英文标题】:Why can this boost::asio::tcp::socket be re-used?为什么这个 boost::asio::tcp::socket 可以重用? 【发布时间】:2018-07-31 16:13:37 【问题描述】:下面是一些代码from a boost::asio example。为什么在构造 chat_session
时移动 socket_
成员是可以的,如果处理程序底部的递归调用将在下次接受发生时将相同的 tcp::socket
传递出去?我认为在移动操作之后,对象不再可以安全使用。
class chat_server
public:
chat_server(boost::asio::io_service& io_service,
const tcp::endpoint& endpoint)
: acceptor_(io_service, endpoint),
socket_(io_service)
do_accept();
private:
void do_accept()
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec)
if (!ec)
std::make_shared<chat_session>(std::move(socket_), room_)->start();
do_accept();
);
tcp::acceptor acceptor_;
tcp::socket socket_;
chat_room room_;
;
【问题讨论】:
【参考方案1】:代码等价于执行以下操作:
some_class o;
while ( true )
// assign a new instance of some_class to the o variable, calling o.bar() is valid
o = some_class(...);
foo(std::move(o));
// o is no longer valid calling o.bar() would fail
对async_accept
的调用将套接字重新初始化为可以使用的有效值。移动的对象处于未指定(但有效)的状态,该状态是什么取决于该对象的实现者。对于asio::tcp::socket
,状态是未初始化的套接字,可用于新连接。
【讨论】:
【参考方案2】:你是对的,套接字对象在移动后不可用。
但是调用您的 lambda 的代码将创建一个 new 套接字并使用该新套接字初始化您的变量 socket_
。所以下次调用你的 lambda 时,它实际上是一个 不同的 套接字。
【讨论】:
除了chat_server
的构造函数之外,我没有看到任何地方创建了新的套接字。
@JimHunziker 它发生在幕后,在调用底层网络代码的代码中。基本上,发生的事情是一个赋值:socket_ = new_socket_object;
(或者可能是一个移动而不是简单的赋值)。【参考方案3】:
标准规定,“移出”对象必须至少处于有效的未指定状态。
移出的套接字可以安全使用,因为它的状态在文档中明确指定:
Following the move, the moved-from object is in the same state as if constructed using the basic_stream_socket(io_context&) constructor.
【讨论】:
以上是关于为啥这个 boost::asio::tcp::socket 可以重用?的主要内容,如果未能解决你的问题,请参考以下文章