首页 > 解决方案 > `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()})socketaiso::async_read(socket, ...)

标签: c++multithreadingc++11boost-asioasio

解决方案


要关闭一个 Tcp 客户端,应该使用哪一个,io_context.stop() 还是 socket.close()?

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

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

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

相反,使用socket::cancel()来取消任何 IO 操作。他们将完成,以便您可以检测情况。如果您控制对象上的所有异步启动,这就足够了。如果您想阻止“其他”方成功启动新的 IO 操作,您可以改为使用套接字。您可以关闭套接字的写入端、读取端或两者。error::operation_abortedshutdown

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

简而言之,最好将套接字句柄与socket实例的生命周期联系起来,并且更喜欢使用cancel()or shutdown()

如果在不同的线程中调用套接字对象(例如,所述线程调用 aiso::async_read(socket, ...)),我需要调用 io_context.post(={socket.stop()})。

是的,线程安全是你的责任。不,post(io_context, ...)当多个线程运行执行上下文时甚至还不够。在这种情况下,您需要更多同步,例如post(strand_, ...). 请参阅为什么在使用 boost::asio 时每个连接都需要 strand?


推荐阅读