使用TCP套接字处理客户端断开连接的最佳方法

时间:2014-01-05 02:50:47

标签: c++ tcp

我设法创建基本的远程管理员工具,它工作正常,我在c ++中使用基本的tcp套接字和多线程。这就像90%完成了我可以用来远程使用它的一些功能,但我的软件没有任何可以检测客户端断开的东西,除非客户端手动关闭,客户端将向服务器发送断开连接消息,但是当用户拔掉网络或其他东西时发生断开连接,处理它的最佳方式是什么,我正在寻找一种专业的方法来做,如果客户端断开连接,服务器将立即检测到哪个客户端断开连接。 / p>

3 个答案:

答案 0 :(得分:3)

空闲TCP连接不必为要维护的连接发送任何数据。您尝试检测的方案称为“半开”连接。史蒂文斯的第7.5章(我的第186页)中有一个选项图表。最终结果如下:

  1. 如果您正在主动发送数据,则连接将超时等待来自远程系统的确认(超时取决于系统,但通常在几分钟的范围内)。
  2. 如果启用了保持活动(并且它们得到适当支持),系统将在2 小时不活动后超时。来自远程系统的不响应将导致超时
  3. 如果您没有启用保持活动并且您没有发送数据,则无法检测丢失的客户端。
  4. 这意味着,如果您想在断开连接时相对快速地关闭连接,则需要添加自己的方式。我通常强迫一方发送某种心跳。

答案 1 :(得分:2)

就像@EJP所说,没有办法立即检测到硬断开,因为本地计算机无法看到整个网络发生的情况,它只能看到它的传出TCP数据包没有被确认了。它无法知道缺少ACK是否是由于一个临时问题(比如一个过载的路由器丢弃了一些数据包,或一条以太网电缆被拉出然后再次快速重新插入)或一个更永久的问题(如远程计算机崩溃,永久断电或断开网络连接。)

您可以做的是确保您的本地应用程序始终定期通过TCP套接字发送数据 - 实际数据,或者如果您没有任何实际数据要发送,请发送一些虚拟字节,客户端将知道要忽略。这些“心跳消息”可以每分钟发送一次,或者每隔几秒发送一次,具体取决于您愿意为此目的使用多少额外带宽。

TCP数据的定期发送将强制您的本地计算机的TCP堆栈监视与发送的数据包对应的ACK;如果它没有收到预期的ACK,它将重新发送数据包,并且在几轮重发之后,它将放弃并关闭TCP连接。大多数TCP堆栈将在几分钟未收到ACK后放弃。

如果“几分钟”对你来说不够快,你可能需要远程程序每隔几秒就向程序发送一些数据,如果你还没有强制关闭TCP套接字从客户端收到任何数据至少(这么多秒)。请注意,根据您设置为超时的秒数,这可能会导致“误报”,其中程序强制关闭实际仍然可行但暂时陷入困境的TCP连接;您的申请可能会或可能不会接受。

答案 2 :(得分:1)

除非客户端正确关闭连接,否则无法立即检测到它。您必须使用读取超时,并对send()或recv()返回的所有其他错误做出正确反应,即关闭套接字。