0

我正在尝试升级我的 C++ TCP 客户端程序以与 Windows 7 兼容。该程序设置为使用非阻塞套接字,它适用于 Windows XP。但是,当我在 Windows 7 中运行相同的代码并发现套接字类中的 recv 函数的行为不同时。

当我尝试从 PC 断开以太网电缆时,Windows XP 和 Windows 7 都检测到系统托盘中的网络已断开连接。然而,

在 Windows XP 中,recv 返回 SOCKET_ERROR 并且 WSAGetLastError 返回 WSAECONNRESET

在 Windows 7 中,recv 返回 SOCKET_ERROR 但 WSAGetLastError 返回 WSAEWOULDBLOCK

我很好奇为什么socket recv 函数仍然认为socket 仍然连接(即返回WSAEWOULDBLOCK)并且只检测到keepalive 超时后断开连接。

除了在调用 recv 函数后检查 WSAGetLastError 的值之外,还有其他方法可以使用 TCP 套接字库检测网络是否断开?

非常感谢!

4

2 回答 2

1

我想说的是,Windows 7 在这里的行为是正确的,而 XP 对电缆拉动立即做出反应是错误的。TCP 从一开始就旨在具有高度容错性,特别是允许电缆拉动或确实路由器中断而不中断现有连接。

有没有其他方法[等]

检测 TCP 连接中断的最可靠方法是发送给它。在足够的缓冲、重试等之后,TCP 将放弃发送并向 send() 的调用者传递一个重置。但这可能需要一段时间,并且需要多次调用。

于 2013-10-23T12:55:26.387 回答
0

您可能正在使用循环select来等待数据,在这种情况下,伪代码的想法是这样的:

bool ping_outstanding = false;
while (running) {
   waitForDataMaxSeconds(5);
   if (dataAvailable()) {
      // all is good
      ping_outstanding = false;
      getData(); // Could be normal data or a ping response
   }
   else if ( !ping_outstanding ) {
      ping_outstanding = true;
      sendPing();
      // I should get data in response to this
   }
   else {
      // I've got connection trouble!
   }
}

当然,您可以根据系统要求调整发送 ping 请求之前等待的时间,并调整期望响应的时间。

如果您使用其他一些“数据等待”指示,您可以使用异步计时器而不是循环,但想法是一样的......如果您没有收到数据,请发送一些请求数据。如果您仍然没有收到数据,则假设存在问题。

于 2013-10-23T13:34:35.110 回答