2009-01-13 78 views
7

我有三個應用程序使用套接字相互交談。他們都可以在自己的機器上生活,但他們也可以共享一臺機器。現在我有兩個人在同一臺機器上,第三臺機器在同一臺機器上。我試圖讓我的通信防彈,所以我拔掉電纜,並殺死應用程序,以確保一切按預期工作。拔下網線時套接字會發生什麼變化?

這裏的東西速寫:

alt text http://i40.tinypic.com/9vch86.png

現在,當我拔掉網線PC2(紅色連接「精讀B」),內部連接停止講話(藍色連接「Con A」)。我從永遠不會到「App 2」的套接字上發送來自「App 1」的東西。

我做了一個機制,發現這一點,並斷開連接,然後重新連接,之後,我可以拔掉所有我想要的電纜和「Con A」只是繼續工作。這只是第一次。

在斷開「Con B」之前,我已確認通過「Con A」進行了通信。
我連接和重新連接完全一樣的方式,它是相同的代碼,所以沒有什麼區別。

發生了什麼事?

由答案觸發的附加信息: PC 1和PC 2共享地址直到最後一個字節。
我有一個內部保活機制,我發送一條消息,並期望每10秒響​​應一次。
當我殺了App 3時,只有拔掉電纜時纔會發生這種情況。

回答

5

你對「Con A」使用什麼地址?如果您使用綁定到外部網絡適配器的地址,即使您正在與同一臺計算機通話,您所描述的內容也可能會發生。

你可以做的是使用地址localhost(127.0.0.1)作爲「Con A」,它應該完全獨立於外部網絡上發生的情況。

5

在某些平臺(窗口)上拉動網絡電纜會告訴網絡堆棧激活使與接口關聯的開放套接字連接失效。

在這種情況下拉網線實際上是一個不好的測試,因爲它提供給您的應用程序的正面反饋,它可能不會在現實生活中收到。

編寫客戶端/服務器應用程序時,人們犯的一個常見錯誤是不包含應用程序層keep-alive或至少在傳輸層啓用keepalive。一個應用程序recv()數據否則可能會永遠無視任何故障條件,直到它寫入(),並且寫入由於傳輸層超時而失敗。

2

取決於您正在運行的操作系統,拉動網線有不同的效果。正如另一張海報所說,Windows檢測到它並使任何現有連接無效。在這種情況下,您的應用程序應該獲得連接關閉消息。

另一方面,我的Linux服務器非常優雅地處理它。經過長時間(30-40秒)的去佈線之後,從我的筆記本電腦到服務器的SSH連接仍然可用並且響應快速。

只要電纜的拔出時間不超過TCP超時時間,堆棧應該能夠緩衝數據包並儘快重新發送數據包。 TCP就是爲此而設計的。如果你不使用TCP,那麼數據包將從網孔中掉出來並蒸發到大氣中。

@einstein:如果您使用select()或衍生物,它會付出努力永遠不會選擇NULL超時。總是有一個明智的超時時間,並檢查套接字狀態是否到期。

+1

不幸的是,如果您只是在等待數據,這不會讓您從不被通知。如果沒有keepalive,可能沒有死對等的OOB通知 - 如果沒有先發送()某些東西,套接字狀態不能用於檢測失敗情況。這就是爲什麼Keepalive非常重要。 – Einstein 2009-01-13 08:57:02

相關問題