c++ - `io_context.stop()` 与 `socket.close()`
问题描述
要关闭一个 Tcp 客户端,应该使用哪一个,io_context.stop()
或者socket.close()
?在做出这样的选择时应该考虑哪些方面?
据我所知,io_context
是线程安全的,而socket
不是。
因此,我可以io_context.stop()
在任何可能与调用的线程不同的线程中调用io_context.run()
. 但是对于,如果在不同的线程中调用对象(例如,所述线程调用)socket.close()
,我需要调用。io_context.post([=](){socket.stop()})
socket
aiso::async_read(socket, ...)
解决方案
要关闭一个 Tcp 客户端,应该使用哪一个,io_context.stop() 还是 socket.close()?
显然socket.cancel()
和或socket.shutdown()
:)
在只有一个 IO 对象(您的套接字)的情况下,停止整个 iexecution 上下文似乎是等效的。但是,一旦您打开了多个套接字或使用计时器和信号集,就很明显为什么要用佳能射击苍蝇了。
另请注意,io_context::stop
它的副作用是清除任何未完成的工作(至少,如果没有reset()
先行就无法恢复),这使得它更像是一种钝器。
相反,使用它socket::cancel()
来取消任何 IO 操作。他们将完成,以便您可以检测情况。如果您控制对象上的所有异步启动,这就足够了。如果您想阻止“其他”方成功启动新的 IO 操作,您可以改为使用套接字。您可以关闭套接字的写入端、读取端或两者。error::operation_aborted
shutdown
关闭通常优于的原因close()
可能非常微妙。一方面,关闭一侧可以让您仍然可以处理/通知另一侧以正常关闭。另一方面,当本机套接字句柄(也)存储在某处时,可以防止非常常见的竞争条件:关闭套接字使本机句柄有资格重复使用,并且不知道更改的客户端可以后来的类型继续使用该句柄,不知道它现在属于其他人。我已经看到生产代码中的错误,由于这种事情,在高负载下 RPC 调用会突然写入数据库服务器。
简而言之,最好将套接字句柄与socket
实例的生命周期联系起来,并且更喜欢使用cancel()
or shutdown()
。
如果在不同的线程中调用套接字对象(例如,所述线程调用 aiso::async_read(socket, ...)),我需要调用 io_context.post(={socket.stop()})。
是的,线程安全是你的责任。不,post(io_context, ...)
当多个线程运行执行上下文时甚至还不够。在这种情况下,您需要更多同步,例如post(strand_, ...)
. 请参阅为什么在使用 boost::asio 时每个连接都需要 strand?
推荐阅读
- wpf - WPF - 如何在 Mahapps HamburgerMenuItem 中使用徽章
- ruby-on-rails - Rails5:fields_for 仅在需要且选中复选框时
- automation - 管理 tosca testsuit 中的选项卡
- html - Angular 测试一个更新值的函数
- pandas - Matplotlib 问题匹配 # of values to # of labels -- ValueError: 'label' must be of length 'x'
- java - SwingWorker get() 冻结接口
- javascript - 在 chrome 中重新映射控制台日志函数调用者来源
- ruby-on-rails - Rails 查询,基于不相关模型的范围
- apache-kafka - librdkafka 生产者的内部队列——它们是如何工作的?
- css - 当 pre/code 内容太长,但希望使内容可滚动时,列向右扩展