10

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

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

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

4

5 回答 5

14

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

这是TCP keepalive 概述,概述了您可能想要使用 TCP keepalive 的一些原因;这个 Linux-specific HOWTO描述了如何配置你的套接字以在运行时使用 TCP keepalive。

看起来您可以通过SIO_KEEPALIVE_VALS使用WSAIoctl()函数进行设置来在 Windows 套接字中启用 TCP keepalive。

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

于 2009-01-30T15:39:42.400 回答
6

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

最简单的解决方案是让客户端定期发送数据,如果服务器在特定时间段内没有收到来自客户端的任何数据,则服务器关闭连接。这非常适用于客户端发送查询和服务器发送响应的查询/响应协议。

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

  1. 服务器响应每个查询。如果服务器在两分钟内没有收到查询,它将关闭连接。

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

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

如果过去一分钟不需要发送查询,让客户端关闭连接可能更简单。由于所有操作都是由客户端发起的,所以如果它需要执行新的操作,它总是可以打开一个新的连接。这将其简化为:

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

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

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

于 2012-09-24T18:24:03.867 回答
2

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

请注意,这是假设您使用的是 TCP/IP。如果您使用的是 UDP,那就是另一回事了,因为它是无连接的。

于 2009-01-30T15:42:39.133 回答
1

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

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

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

于 2009-01-30T15:52:07.790 回答
0

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

于 2009-01-30T15:42:35.483 回答