我們正面臨着一個奇怪的問題,即關閉一個死的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