12

我有一个客户端服务器的情况,客户端打开一个到服务器的 TCP 套接字,有时很长一段时间会过去而没有数据在它们之间发送。我遇到了服务器尝试向客户端发送数据的问题,并且似乎成功,但客户端从未收到它,并且几分钟后,客户端似乎断开连接。

我是否需要每隔一段时间发送某种保持活动数据包?

编辑:要注意,这是同一台计算机上的同行。该计算机位于 NAT 后面,该 NAT 将使用的一系列端口转发给该计算机。与服务器连接的客户端通过 DNS 打开连接。即它使用mydomain.net & 端口连接。

4

4 回答 4

9

在 Windows 上,没有发送数据的套接字是许多应用程序中的一大麻烦,必须正确处理。

问题是,SO_KEEPALIVE 的周期可以在系统范围内设置(否则,默认值是无用的两个小时)或使用后来的 winsock API。

因此,许多应用程序确实不时发送一些数据字节(被对等方忽略),只是为了使网络层在未收到 ACK 后声明断开连接(在该层完成所有应有的重传和 ack 超时之后)。

回答您的问题:不,套接字不会自动断开连接。

但是,您必须小心上述问题。更复杂的是,测试这种行为非常困难。例如,如果您正确设置了所有内容并且希望正确检测断开连接,则无法通过断开物理层来测试它。这是因为 NIC 将感知载波丢失,并且套接字层将发出信号以关闭所有依赖它的应用程序套接字。测试它的一个好方法是连接两台计算机,它们之间有 3 个腿和两个开关,断开中间腿,从而防止载波丢失,但仍然物理断开机器。

于 2012-07-30T00:42:50.013 回答
0

TCP 内置了一个超时,但您可以调整它,请参阅SendTimeoutSocketReciveTimeout但我怀疑这不是您的问题。NAT 路由器在将 TCP 连接从其端口转发表中删除之前也可能有一个过期时间。如果在路由器上的超时时间内没有流量通过,它将阻止所有传入流量(因为它从内存中清除了转发信息,因此它不知道将流量发送到哪台计算机),传出连接也可能有不同的源端口,因此服务器可能无法将其识别为相同的连接。

于 2012-07-29T19:54:52.367 回答
0

使用 Keep-alive 选项(Linux 下的 SO_KEEPALIVE)更安全,以防止由于不活动而断开连接,但这可能会产生一些额外的数据包。

此示例代码在 linux 下执行:

int val = 1;
....
// After creating the socket
if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&val, sizeof(val)))                   
    fprintf(stderr, "setsockopt failure : %d", errno);

问候。

于 2012-07-30T00:45:21.937 回答
-1

TCP 套接字根本不会自动关闭。但是 TCP连接可以。但是,如果这发生在同一台计算机中的对等点之间,则只要两个对等点都存在并且它们的套接字打开,就永远不应该断开连接。

于 2012-07-30T00:33:14.687 回答