在C ++中实现心跳检查套接字连接的最佳方法是什么?

时间:2009-01-30 15:32:27

标签: c++ sockets heartbeat

嘿帮派。我刚刚使用sys / socket在C ++中编写了一个客户端和服务器。我需要处理客户端仍处于活动状态但服务器已关闭的情况。建议的方法之一是使用心跳来定期断言连接。如果没有尝试在Y时间段内每隔X秒重新连接一次,那么就超时了。

这种“心跳”是检查连接的最佳方式吗?

我正在使用的套接字可能有关于它的信息,有没有办法检查是否有连接而没有弄乱缓冲区?

5 个答案:

答案 0 :(得分:12)

如果您在IP网络上使用TCP套接字,则可以使用TCP协议的keepalive功能,该功能将定期检查套接字以确保另一端仍然存在。 (这样做的好处还在于保持套接字的转发记录在客户端和服务器之间的任何NAT路由器中都有效。)

这是TCP keepalive overview,其中概述了您可能希望使用TCP keepalive的一些原因; this Linux-specific HOWTO描述了如何配置套接字以在运行时使用TCP keepalive。

通过使用WSAIoctl()函数设置SIO_KEEPALIVE_VALS,您似乎可以在Windows套接字中启用TCP keepalive。

如果您使用的是基于IP的UDP套接字,则需要在协议中构建自己的心跳。

答案 1 :(得分:3)

是的,这种心跳是最好的方式。您必须将其构建到服务器和客户端用于通信的协议中。

最简单的解决方案是让客户端定期发送数据,如果服务器在特定时间段内未从客户端收到任何数据,则服务器会关闭连接。这适用于查询/响应协议,其中客户端发送查询并且服务器发送响应。

例如,您可以使用以下方案:

  1. 服务器响应每个查询。如果服务器在两分钟内未收到查询,则会关闭连接。

  2. 客户端发送查询并在每个查询后保持连接打开。

  3. 如果客户端没有发送一分钟的查询,它会发送“你在那里”查询。服务器回答“是的我是”。这将重置服务器的两分钟计时器,并向客户端确认连接仍然可用。

  4. 如果客户端不需要发送过去一分钟的查询,那么让客户端关闭连接可能会更简单。由于所有操作都是由客户端启动的,因此只有在需要执行新操作时才能打开新连接。这减少到这个:

    1. 如果服务器在两分钟内未收到查询,则会关闭连接。

    2. 如果客户端在一分钟内无需发送查询,则会关闭连接。

    3. 但是,这并不能确保客户端服务器存在并随时准备接受查询。如果您需要此功能,则必须在协议中实现“你在那里”,“我是”查询/响应。

答案 2 :(得分:2)

如果另一方已经消失(即进程已经死亡,机器已经关闭等),尝试从套接字接收数据应该会导致错误。但是,如果另一侧仅挂起,则插座将保持打开状态。在这种情况下,有心跳是有用的。确保您使用的任何协议(在TCP之上)支持某种“无所事事”请求或数据包 - 每一方都可以使用它来跟踪他们最后一次从另一方收到的东西,然后可以如果数据包之间的时间过长,请关闭连接。

请注意,这假设您使用的是TCP / IP。如果你正在使用UDP,那那就是另外一条鱼,因为它是无连接的。

答案 3 :(得分:1)

好吧,我不知道你的程序做了什么或者什么,所以也许这是不可行的,但我建议你避免尝试始终保持套接字打开。它应该只在您使用时打开,并且在您不使用时应该关闭。

如果您在读取和写入之间等待用户输入,请关闭套接字。设计您的客户端/服务器协议(假设您手动执行此操作而不使用任何标准协议(如http和/或SOAP))来处理此问题。

如果断开连接,套接字将会出错;编写程序,以便在写入套接字期间出现此类错误时不会丢失任何信息,并且在从套接字读取期间出现错误时不会获取任何信息。应将事务性和原子性纳入您的客户端/服务器协议(同样,假设您自己设计它)。

答案 4 :(得分:0)

也许这会对你有帮助,TCP Keepalive HOWTO 或者SO_SOCKET