检测断开连接的客户端套接字连接(跨平台适用性)

时间:2016-07-14 05:32:51

标签: c sockets tcp network-programming client-server

我知道这个问题有数百个答案,但我无法完成我的情况。场景是这样的,我们有一个用TCP / IP协议编写的服务器,我们有多个客户端连接到这个服务器。这里的客户端是一个软件模块,在客户机启动之前,它在服务器中注册它并加载功能。但问题是这个软件模块崩溃并且没有socket.close()被调用,这将使其脚印仍然存在于服务器中,即使它崩溃了。怎么认识到这个?

我在客户端使用select()方法来通知客户端和服务器的任何信息(反之亦然)  我无法为服务器中的每个客户端请求单独创建进程,也无法在客户端计算机中创建父子机制。  tcp-keepalive不适用,因为我们需要调整Windows中的注册表?我需要一个x平台兼容的解决方案。 我已经读过recv()到服务器代码中连接的套接字会返回一些值来自'套接字关闭了0等客户端?我可以用它来清除服务器数据库中的客户端套接字注册吗?这有用吗?

2 个答案:

答案 0 :(得分:0)

您没有指定用于处理服务器端代码中的套接字事件的方法。无论轮询您正在使用的套接字的方法是什么,recv()将在客户端崩溃时返回0或可能 -1 / SOCKET_ERROR

要检测非活动客户端连接,大多数服务器应用程序会在应用程序层协议中定期发送某种形式的心跳或ping消息。当无法从客户端发送ACK时,服务器应用程序将通过recv()通过SOCKET_ERROR返回0或WSAENETRESET,并使用WSAECONNABORTED,{{1}之类的错误代码来通知客户端已断开连接},WSAETIMEDOUTWSAECONNRESET(请参阅各种错误代码here)。通常在服务器将心跳发送到不再处于活动状态的客户端TCP端口后,将发送ICMP数据包作为响应,该数据包将警告您的服务器端口或主机未处于活动状态(recv()将立即通知您此事件)

如果您希望打开TCP keep alive计时器,可以使用套接字选项SO_KEEPALIVE。也可以使用SIO_KEEPALIVE_VALS设置间隔。

编辑:请记住各种错误代码和选项SIO_KEEPALIVE_VALS是特定于Win32的。要为其他操作系统处理这些事件,您需要使用特定于操作的方法来检索错误代码并设置TCP保持活动间隔(如果您选择这样做)。保持代码跨平台兼容的最佳建议是在应用程序或其他特定于应用程序层的超时中简单地实现应用程序层心跳消息。这样做可以让您忘记管理TCP保持活动。

更新

我无法对EJP的答案发表评论,但重要的是要指出,通过调用send(),他实际上建议您在协议的应用程序层中实施心跳/ ping消息。检查send()的返回值很重要,如果您正在轮询/选择读取事件,则在TCP认为连接被视为中断时,将在调用recv()时立即断开TCP连接断开连接的通知堆。如果您等待应用程序计时器尝试使用send()发送一些数据,可能需要几秒钟(取决于间隔计时器的长度)recv()已经通知您连接断开。换句话说:请注意recv()返回值以及send()返回值。

答案 1 :(得分:-1)

  

tcp-keepalive不适用,因为我们需要调整Windows中的注册表?

如果您可以接受两小时的默认超时,则可以选择TCP keepalive。

  

我需要一个x平台兼容的解决方案。

TCP keepalive是跨平台的。

  

我已经读过recv()到服务器代码中的连接套接字将从'那个'客户端返回一些值,例如0,以便套接字关闭?

如果对等体关闭其套接字,它将返回零,并且如果对等进程仅在不关闭它的情况下退出,则在某些平台上返回。

  

我可以用它来清除服务器数据库中的客户端套接字注册吗?这有用吗?

只有你可以依赖对手正确关闭套接字。

在我看来,您应该做的是调试客户端代码,使其不会崩溃,并使用TCP keepalive作为长期备份。

您还应该知道send()对已退出的对等体迟早会因ECONNRESET错误而失败。