我正在开发一个 Windows (Microsoft Visual C++ 2005) 应用程序,该应用程序使用在 Intranet 的不同主机上运行的多个进程。
进程使用 TCP/IP 相互通信。不同的进程可以在同一台主机上,也可以在不同的主机上(即通信既可以在同一台主机内,也可以在不同主机之间)。
我们目前有一个不规则出现的错误。通信似乎工作了一段时间,然后停止工作。然后它再次工作一段时间。
当通信不起作用时,我们会收到一个错误(显然是在一个进程试图发送数据时)。调用如下所示:
send(socket, (char *) data, (int) data_size, 0);
通过检查我们得到的错误代码
WSAGetLastError()
我们看到这是一个错误 10054。这是我在 Microsoft 文档中找到的内容(请参阅此处):
WSAECONNRESET
10054
Connection reset by peer.
An existing connection was forcibly closed by the remote host. This normally
results if the peer application on the remote host is suddenly stopped, the
host is rebooted, the host or remote network interface is disabled, or the
remote host uses a hard close (see setsockopt for more information on the
SO_LINGER option on the remote socket). This error may also result if a
connection was broken due to keep-alive activity detecting a failure while
one or more operations are in progress. Operations that were in progress
fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.
因此,据我了解,连接被接收过程中断。在某些情况下,此错误(AFAIK)是正确的:一个进程已终止,因此无法访问。在其他情况下,发送方和接收方都在运行并记录活动,但由于上述错误(错误在日志中报告),它们无法通信。
我的问题。
- SO_LINGER 选项是什么意思?
- 什么是保持活动,它如何断开连接?
- 如何避免这个问题或从中恢复?
关于最后一个问题。我们尝试的第一个解决方案(实际上,这是一种解决方法)是在发生错误时重新发送消息。不幸的是,同样的错误在一段时间(几分钟)内一遍又一遍地发生。所以这不是一个解决方案。
目前我们不明白是软件问题还是配置问题:也许我们应该在 Windows 注册表中检查一些东西?
一个假设是操作系统耗尽了临时端口(如果连接关闭但端口由于 TcpTimedWaitDelay 而未释放),但通过分析这个问题,我们认为应该有很多:即使没有消息也会出现问题进程之间发送过于频繁。但是,我们仍然不能 100% 确定我们可以排除这种情况:临时端口会以某种方式丢失(???)
另一个可能有帮助的细节是,发送和接收在每个进程中同时发生在不同的线程中:TCP/IP 库中是否存在可能损坏的共享数据结构?
同样很奇怪的是,问题出现的不规律:通讯正常几分钟,然后几分钟不通,然后又通了。
感谢您的任何想法和建议。
编辑
感谢您确认唯一可能的解释是连接关闭错误的提示。通过对问题的进一步分析,我们发现连接的服务器端进程已崩溃/已终止并已重新启动。所以有一个新的服务器进程正在运行并在正确的端口上侦听,但客户端没有检测到这一点,并且仍在尝试使用旧连接。我们现在有一种机制来检测这种情况并在客户端重置连接。