如何在Boost.Asio中检查套接字是否已关闭?

9
什么是检查远程连接socket是否关闭的最简单方法?即使在远程端关闭时,socket::is_open()也会返回true(我正在使用boost::asio::ip::tcp::socket)。
我可以尝试从流中读取并查看是否成功,但我必须更改程序的逻辑才能以这种方式工作(我不希望在检查点提取数据流)。

你为什么需要知道远程连接是否已关闭? - outis
另外,您是使用自己设计的应用协议还是标准协议? - outis
我正在编写一个基本的聊天程序,需要通知用户另一个人关闭了应用。我有自己的协议,并已经添加了“退出”消息。唯一的缺点是,如果应用程序被杀死/崩溃等,则不会发送该消息。 - Hali
你的问题表述不清。你所要求的是一种检测对等方是否关闭了连接的方法。 - user207421
也许你可以使用 boost::asio::null_buffers 实例作为缓冲参数执行异步或同步读取操作? - Florian
6个回答

13

在你的async_receive处理程序中仅需检查boost::asio::error::eof错误即可。它表示连接已关闭。这是处理此问题的唯一正确方式。


8
有没有可用的boost peek函数?大多数套接字实现都有一种方法可以读取数据而不将其从队列中删除,因此您稍后可以再次读取它。这似乎满足您的要求。
快速浏览asio文档后,我没有找到我期望的内容,但这并不意味着它不存在。
我建议从这里开始。

是的,你说得对。你可以向“receive”方法传递一个标志,告诉它不要删除数据。我一直在使用“read_some”方法,它没有这个标志参数。谢谢你指出来! - Hali
假设您已经设置了套接字和响应,那么您可以设置一个流,例如:std::istream myhttpstream(&presponse); 然后您可以使用 std::istream::peek() 函数。 - user677656
我这样做:received = socket().receive(boost::asio::buffer(buf), tcp::socket::message_peek); - Chuck D

7
如果连接已被对端干净地关闭,您应该在读取时收到EOF。否则,我通常会发送ping来确定连接是否真的存在。

2
我需要读取以获取EOF。 我想那就没有其他办法了。 谢谢! - Hali

2

我认为一旦打开套接字,应立即开始读取,并且始终如此。这样,您可以使您的服务器或客户端支持同步和异步协议。当客户端关闭连接时,读取操作将告诉您。


我看不出“立即开始阅读并永不停止”和“使您的服务器或客户端支持同步和异步协议”的任何关系。您能否为我详细解释一下? - John

0
boost::asio::socket_base::keep_alive keepAlive(true);
peerSocket->set_option(keepAlive);

启用对等套接字的保持活动功能。使用本机套接字调整保持活动间隔,以便在连接关闭时,异步接收处理程序在读取时立即获得EOF。

使用boost::asio配置TCP keep_alive


0

使用 error_code 可以检查客户端是否连接。如果连接成功,error_code.error.value() 将返回 0,否则返回其他值。您还可以从 error_code 检查 message()。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接