簡體   English   中英

Windows下的奇怪的tcp死鎖

[英]Odd tcp deadlock under windows

我們正在移動LAN上的大量數據,並且必須非常快速和可靠地進行。 目前我們使用在C ++中實現的Windows TCP。 使用大(同步)發送比一堆較小(同步)發送更快地移動數據,但是經常會在大的時間間隔(.15秒)內死鎖,導致整體傳輸速率驟降。 這種僵局發生在非常特殊的情況下,這使我相信它應該完全可以預防。 更重要的是,如果我們真的不知道原因我們真的不知道它不會發生在一段時間內使用較小的發送。 誰能解釋這個僵局?

死鎖描述(好的,僵屍鎖定,它沒有死,但是.15秒左右它停止,然后再次啟動)

  1. 接收方發送ACK。
  2. 發送方發送包含消息結束的數據包(設置推送標志)
  3. 對socket.recv的調用大約需要.15秒(!)才能返回
  4. 關於呼叫返回的時間,接收方發送ACK
  5. 最后發送來自發送方的下一個數據包(為什么它在等待?tcp窗口很大)

關於(3)的奇怪之處在於,通常該調用不需要花費太多時間並且接收完全相同數量的數據。 在2Ghz的機器上,有3億條指令值得花時間。 我假設呼叫沒有(天堂禁止)等待收到的數據在返回之前被激活,所以ack必須等待呼叫返回,否則兩者必須被其他東西延遲。

當第二個數據包(同一個消息的一部分)到達1到2之間時,問題永遠不會發生。這部分非常清楚地說明它與Windows TCP不會發回的事實有關 - 數據ACK,直到第二個數據包到達或200ms計時器到期。 但是延遲小於200毫秒(更像是150毫秒)。

第三個不合時宜的角色(在我看來真正的罪魁禍首)是(5)。 發送肯定是在那之前調用好.15秒,但是數據永遠不會在ack返回之前點擊線路。 對我來說,這是這個僵局中最離奇的部分。 它不是tcp阻塞,因為TCP窗口很大,因為我們將SO_RCVBUF設置為類似500 * 1460(仍然在meg以下)。 數據進入非常快(基本上有一個循環通過發送旋轉數據)所以緩沖區應該幾乎立即填充。 Msdn提到在決定發送命中何時使用各種“啟發式”,並且已經掛起的發送+完整緩沖區將導致發送阻塞,直到數據到達線路(否則發送顯然只是將數據復制到tcp發送緩沖區並返回)。

不管怎樣,為什么發送者實際上並沒有發送更多數據.15秒暫停對我來說是最離奇的部分。 上面的信息是通過wireshark在接收端捕獲的(當然除了在文本文件中記錄的socket.recv返回時間)。 我們嘗試將發送緩沖區更改為零並關閉發送方上的nagel(是的,我知道nagel不會發送小數據包 - 但我們嘗試關閉nagel,以防這是未聲明的“啟發式”的一部分,影響消息是否會從技術上來說,微軟的nagel就是如果緩沖區已滿並且有一個未完成的ACK,則不會發送一個小數據包,所以它似乎是一種可能性。

發送阻塞直到接收到前一個ACK幾乎可以肯定地表明TCP接收窗口已滿(您可以通過使用Wireshark來分析網絡流量來檢查)。

無論您的TCP窗口有多大,如果接收應用程序沒有像到達那樣快速處理數據,那么TCP窗口最終會填滿。 我們在這里談得多快? 接收方對數據做了什么? (如果您將接收到的數據寫入磁盤,那么您的磁盤很可能無法滿足千兆網絡的需求)。


好的,所以你有一個730,000字節的接收窗口,你正在以480Mbps的速度傳輸數據。 這意味着完全填滿你的窗口只需要12ms - 所以當接收端的150ms延遲發生時,接收窗口幾乎立即填滿並導致發送器停止。

因此,您的根本原因是計划接收過程的延遲時間為150毫秒。 有許多事情可能導致這種情況(可能就像內核需要將臟頁面刷新到磁盤以便為您的應用程序創建更多空閑頁面一樣簡單); 你可以嘗試增加你的進程調度優先級,但不能保證這會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM