安全地完成读取操作 (Boost.Asio)

Posted

技术标签:

【中文标题】安全地完成读取操作 (Boost.Asio)【英文标题】:Safely make a read operation complete (Boost.Asio) 【发布时间】:2015-09-07 06:15:58 【问题描述】:

通过完成读取操作,我的意思是让socket::read_some 返回或调用传递给socket::async_read_some 的处理程序。请注意,我在套接字的接收方,是我发起了读取操作。我想要完成的是主动关闭一个套接字连接。连接也可能是被动关闭的,这由以boost::asio::error::eof完成的读取操作指示。

我尝试过socket::shutdown(),然后调用socket::close(),如下所示:

boost::system::error_code err;
if (psocket->is_open()) 
    psocket->shutdown(tcp::socket::shutdown_both, err);
    psocket->close(err);

这种方法的问题是,如果在调用is_open()返回true后被动关闭连接,那么在Mac OS X等某些操作系统上,对close()的以下调用将导致分段通过访问已经为空的指针来出错。另一方面,对shutdown() 的一次调用根本不会完成读取操作。那么,如何主动让读取操作安全地完成呢?

【问题讨论】:

不清楚你在说什么部分。您是否从发送端关闭?为什么不显示哪一侧发生了什么(图表可能会有所帮助) 我用的方法和你一样,在Linux环境下我从来没有遇到过你的问题。也许值得向 asio 维护者开张票要求澄清? @sehe 很抱歉描述不清楚。现已更新。 【参考方案1】:

您不能强制异步操作​​完成状态。但是您可以通过调用psocket->cancel() 来取消对套接字的所有操作。这将使用boost::asio::error::operation_aborted 错误代码调用您的所有处理程序。

【讨论】:

我不相信 OP 正在谈论接收方取消。并且取消异步操作发送方不会在接收端发出“operation_aborted”信号,我不认为 @sehe 可能我误解了他的问题,但他似乎想取消自己的待处理回调 @PSIAlt cancel() 似乎是我需要的。 shutdown() 阻止未来对套接字的操作,cancel() 然后处理过去。尽管文档说cancel() 仅适用于异步操作,但根据我的测试运行,它至少在我的 Windows 7 上也适用于同步读取。但是,正如文档所述,它确实存在可移植性问题。那么,有没有更好的选择? @Lingxi 目前似乎别无选择,文档说cancel 在 Win2003 和更早版本上可能会出现问题。我在linux和macos上使用asio,对windows不熟悉,但是看起来除了关闭socket没有其他100%的方法了。 @Lingxi 您的测试运行听起来好像违反了线程安全并调用了未定义的行为。如果close() 正在使程序崩溃,我会非常怀疑是否还会调用未定义的行为。

以上是关于安全地完成读取操作 (Boost.Asio)的主要内容,如果未能解决你的问题,请参考以下文章

C++ Boost ASIO:如何读取/写入超时?

Boost.ASIO 性能不佳

Boost Asio总结class address

boost::asio 学习

试图了解 Boost.Asio 自定义服务实现

boost--asio