2016-08-29 40 views
0

作爲網絡工程師,我非常熟悉TCP操作。作爲程序員,我涉足套接字編程,但從未寫過任何生產服務。TCP半開連接,Winsock,監聽/接受行爲

我們有一個與PTZ(平移/傾斜/變焦)相機集成的供應商系統。照相機看病人。相機數據被傳送到供應商服務器。供應商服務器將攝像機數據傳送給客戶端。 (它更多,但這是簡單的情況。)如果客戶想調整攝像頭,客戶端會將自定義命令發送到供應商服務器上的自定義服務。服務器解釋命令並將其發送到相機。相機移動。

我們遇到了服務器上的PTZ服務崩潰的問題。在測試過程中,通過網絡捕獲,我們發現服務在nmap執行半開(初始)連接時崩潰 - nmap發送SYN,服務器使用SYN/ACK回覆,nmap未發送最終ACK。服務器發送重複的SYN/ACK嘗試完成會話並失敗。

我想了解的:服務使用listen來監視TCP連接,然後使用accept接受連接。 listen在什麼時候告訴服務有一個新的連接,準備好accept ed?在listen將服務傳遞給服務之前,TCP連接是否需要完成?accept ed?或者服務器只需要在listen告知服務之前返回SYN/ACK?

如果握手需要完成 - SYN,SYN/ACK,ACK - 在listen之前告訴服務,那麼我可能會走錯了路。如果套接字只需要達到SYN/ACK,那麼服務處理不完整的會話可能會有問題。其他測試,我們完成TCP會話併發送虛假數據,試圖讓服務崩潰 - 並未導致服務失敗。但重複nmap測試非常可靠地崩潰,所以我傾向於半開連接問題。

回答

0

listen()本身只是創建積壓隊列,打開綁定的通信端口,然後退出。 在幕後,套接字棧現在被動地監聽OS層的連接,緩存待辦事務隊列中的掛起連接並完成握手。只有完全建立的連接可用於accept()WSAAccept()AcceptEx()

listen()後退出,這取決於模式的應用程序代碼使用套接字I/O(阻擋,不堵塞,重疊I/O或I/O完成端口)時,代碼可以:

  1. (阻止)調用accept()WSAAccept()並讓它阻塞,直到它從隊列中檢索連接。

  2. (非阻塞)使用select()WSAAsyncSelect(),或WSAEventSelect()當連接是準備和等待與accept()WSAAccept()被檢索時得到通知。

  3. (overlapped/iocp)調用AcceptEx()開始異步接受,然後等待事件/完成通知指示已從隊列中檢索到連接。

+0

我想我已經得到了。因此,想象一下供應商系統的黑盒子,供應商可能坐在'select()'而不是'listen()'上。 所以在第2點,當連接「準備就緒並等待」時。 。 。這是否意味着握手已完成?客戶端發送了TCP ACK?還是可以等待最終客戶端的ACK? –

+1

正如我在我的回答中所述:「*只有**完全建立**連接可用於'accept()',... *」。所以是的,在代碼看到連接之前,連接的握手必須完成。 –

+0

謝謝雷米。非常感謝。這將表明半開連接不會破壞服務,所以它必須被髮送到服務。但我們無法確定它是什麼。現在我明白了listen(),select()和accept()與協議棧是如何協同工作的,我會繼續研究。再次感謝! –

0

在什麼時候聽告訴服務有一個新的連接,隨時可以接受?

從來沒有。

在將listen傳遞給要接受的服務之前TCP連接是否需要完成?還是服務器只需要在偵聽告訴服務之前返回SYN/ACK?

沒有發生這種情況。 listen()只是將套接字置於LISTEN狀態,並使TCP開始接受連接並將它們放入積壓隊列中。與服務進行通信的是accept():它在積壓隊列爲空(本質上)時阻塞,然後返回第一個條目並在其周圍構造一個新的套接字。

如果握手需要完成 - SYN,SYN/ACK,ACK - 聽之前告訴服務,那麼我可能會走錯了路。

accept()將返回一個新的套接字到服務之前,它需要完成。

如果套接字只需要達到SYN/ACK,那麼服務處理不完整的會話可能有問題。

不是問題。它不像那樣。

其他測試中,我們完成TCP會話併發送虛假數據,試圖讓服務崩潰 - 並未導致服務失敗。

QED。

但重複的nmap測試很可靠地崩潰,所以我傾向於半開連接問題。

請定義'崩潰'。

+0

供應商服務,所以不能在「崩潰」時明確。 「鎖定」可能是一個更好的術語,但我們無法確定。沒有日誌條目。相機在客戶端和服務器屏幕上灰顯,無法移動相機,有時相機會在故障時隨機指向不同的方向。重新啓動PTZ服務可以在5次以內運行4次;其他時間服務器需要重啓。供應商稱已知會造成問題的端口掃描。我們正在努力確定具體情況和原因,以便我們可以告訴供應商修復您的問題。 –