`io_context.stop()` 与 `socket.close()`

`io_context.stop()` vs `socket.close()`

要关闭一个Tcp客户端,应该使用哪个,io_context.stop()还是socket.close()?做出这样的选择应该考虑哪些方面?

据我所知,io_context 是线程安全的,而 socket 不是。

因此,我可以在任何可能与调用 io_context.run() 的线程不同的线程中调用 io_context.stop()。 但是对于 socket.close(),如果在不同的线程中调用 socket 对象(例如,所述线程调用 aiso::async_read(socket, ...)),我需要调用 io_context.post([=](){socket.stop()})

To close a Tcp client, which one should be used, io_context.stop() or socket.close()?

显然 socket.cancel() 和或 socket.shutdown() :)

在只有一个 IO 对象(您的套接字)的情况下,停止整个 iexecution 上下文似乎是等效的。但是,一旦您打开了多个套接字或使用了定时器和 signal_sets,就很明显为什么这是用佳能射苍蝇了。

另请注意,io_context::stop 具有清除所有未完成工作的副作用(至少,如果没有先 reset() 就无法恢复),这使它更像是一个钝器。

相反,请使用 socket::cancel() 取消对其 的任何 IO 操作。它们将以 error::operation_aborted 结尾,因此您可以检测到这种情况。如果您控制对象上的所有异步启动,这就足够了。如果你想阻止“其他”方成功开始新的 IO 操作,你可以 shutdown 套接字。您可以关闭套接字的写入端、读取端或两者。

关闭通常优于 close() 的原因可能非常微妙。一方面,关闭一侧使您仍然可以 handle/notify 另一侧正常关闭。另一方面,当本机套接字句柄(也)存储在某个地方时,可以防止非常常见的竞争条件:关闭套接字使本机句柄有资格重新使用,并且不知道更改的客户端可以在后来的类型继续使用该句柄,不知道它现在属于其他人。我已经看到生产代码中的错误,由于这种情况,在高负载下 RPC 调用会突然写入数据库服务器。

简而言之,最好将套接字句柄绑定到socket实例的生命周期,并且更喜欢使用cancel()shutdown()

I need to call io_context.post(={socket.stop()}) if socket object is called in a different thread(e.g. the said thread calls aiso::async_read(socket, ...)).

是的,线程安全是你的责任。不,当多个线程是 运行 执行上下文时,post(io_context, ...) 甚至还不够。在那种情况下,你需要更多的同步,比如 post(strand_, ...)。参见 Why do I need strand per connection when using boost::asio?