我们正面临着一个奇怪的问题,即关闭一个死的TCP套接字(由拔掉电线引起)会影响另一个正常的打开的TCP套接字。下面是详细的信息:为什么要关闭一个死的TCP套接字会影响另一个打开的TCP套接字?
拓扑
客户端A←→开关A←路由器A:NAT←.. ..网络→ 路由器B:NAT→交换机B←→服务器B问题:
假设客户端和服务器之间存在由于拔下导线而导致的死连接。拔掉电缆(机器和交换机之间)后,我们从另一台机器登录客户端A,现在客户端和服务器之间会有一个新的tcp连接,并且此连接正常。我们从服务器发现,如果我们在tcp内核仍在重新传输数据的时候关闭死tcp连接,那么其他tcp连接似乎会受到污染,从客户端到服务器的方向将变得不可用意味着客户端通过连接发送的数据永远不会被服务器接收到,但令我们惊讶的是从服务器到客户端的其他方向仍然正常,通过服务器发送到客户端的相同tcp套接字数据机。
但是,如果我们等待直到死连接的tcp数据传输停止, 2小时,然后关闭套接字,然后其他TCP连接保持OK。
以下是此问题的详细步骤:
1,有两个客户端这两者都是背后路由器A:NAT时,NAT是全锥。
2.路由器B后面有一台linux服务器:NAT,NAT是full-cone,但是这里使用端口转发。
3.四台机器和两个客户说他们是X,Y,服务器说它是S。
4. X和Y的登录和设置一个视频会议,现在他们都创建TCP连接到服务器,说他们是信道CX和CY通道
5.拔掉机的电缆上,其中Y是客户端运行,现在频道CY已经坏掉了。但通道CX仍然正常。
6.从第四台机器登录Y,再次与X建立视频会议,现在有一个新的tcp通道,说它是CY2。
结果:
在步骤6中,如果服务器关闭死连接 - CY --in分钟,然后将新的信道CY2将成为单向 - 从客户端Y发出水湿到达数据服务器包含ACK数据包,而反过来则可以。
如果服务器关闭了死连接 - CY - 在很长时间内这样2个小时,那么没有问题发生。
这个问题只发生在通过NAT运行时,至少当我们在同一个局域网内运行这些应用程序(不需要遍历NAT)时,我们从不再重现它。
有人知道为什么会发生?
编辑:
在服务器端,我们使用非阻塞tcp套接字和选择模型。
psuedocode:
//server
listenfd = socket(,SO_STREAM,);
localAddr.port = htons(8013);
localAddr.ip = inet_addr(INADDR_ANY);
bind(localAddr...)
listen(listenfd, 100);
...
//using select model
select(maxFd, &fdSet, NULL, NULL);
for(...)
{
if (FD_ISSET(listenfd))
{
fd = accept(...)
set_non_block(fd);
...
}
...
}
更多信息:第一机器上
1)连接部分A:192.168.10.4:13000←→...←路由器A:NAT← - 现在:从PublicIP:8661(随机)。 .Network ..→Router B:NAT(到端口:8013,端口转发)→...←→服务器B
2)第二台机器上的连接B:192.168.10.7:13000←→... ←Router A:NAT←Now:from PublicIP:8777(random).. Network ..→Router B:NAT(to port:8013,端口转发)→...←→服务器B
3)拔下线路和连接A死了,现在在第三台机器上创建一个新的连接C:192.168.10.10:13000←→...←路由器A:NAT←-Now:从PublicIP:8869 (随机)..网络..→路由器B:NAT(到端口:8013,端口转发)→...←→服务器B
如果我们关闭连接A从服务器,然后连接C将成为单向,但如果我们在2小时内关闭服务器的连接A,则连接C仍然正常。
如果客户端A和服务器B之间只有一条路由,服务器在拔出线路时如何与客户端建立连接? – jxh 2013-03-11 22:50:41
@ user315052有许多机器连接到LAN中的交换机,所有这些机器共享一个公共IP。 – Steve 2013-03-11 23:04:59
所以你说你拔掉了交换机和路由器之间的电缆,但交换机和路由器之间可能有多条电缆?我试图想象如何重现你的问题,但我似乎无法弄清楚。 – jxh 2013-03-11 23:08:18