2013-07-24 72 views
2

我正在編寫一個客戶端應用程序,該應用程序應該從服務器接收文件。通訊使用了一個通過TCP設計的非常簡單的專有協議:服務器發送一塊16KB的數據,等待來自客戶端的簡單響應,然後進入下一個塊;這完成,直到文件完全傳輸。延遲10ms的TCP ACK響應

服務器在Windows上運行。如果我在Windows上運行我的客戶端(通過Cygwin),我實現了70Mbits/s的吞吐量。但是,如果我在Linux上運行它,我能夠獲得的最大吞吐量是5Mbits/s(兩個測試使用相同的100Mb以太網鏈路)。

對我收集的tcpdump跟蹤進行了一些調查後,我發現Linux需要大約10ms來回答每個TCP ACK。我試過在每次調用recv()後都禁用了sockoption TCP_QUICKACK,但沒有成功。我還沒有發現任何其他可以改變這種行爲的TCP選項(在bsd套接字下或甚至在Linux下)。

任何人都可以幫助我弄清楚發生了什麼?

  1. 我的客戶端是用C++編寫的,使用BSD套接字。 TCP_NODELAY sockoption被設置。
  2. 我的Linux內核是2.6.19
  3. 專有協議和服務器不是我的,所以我無法以任何方式更改它們。

下面是我分析的tcpdump跟蹤的一個示例。這是一個塊傳輸。服務器IP爲10.200.252.1,客戶端爲10.200.252.2。與**開頭的行是TCP ACK數據包與10ms的延遲:

5184 28.060969 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4736738 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5185 28.060978 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4738182 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5186 28.060981 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4739626 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5187 28.060987 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4741070 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5188 28.060990 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4742514 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5189 28.060994 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4743958 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5190 28.060997 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4745402 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5191 28.061000 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4746846 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5192 28.061003 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4748290 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5193 28.061007 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4749734 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5194 28.061038 10.200.252.1   10.200.252.2   TCP  1510 search-agent > 58358 [ACK] Seq=4751178 Ack=1741 Win=66048 Len=1444 TSval=2951472 TSecr=2921060 
    5195 28.061042 10.200.252.1   10.200.252.2   TCP  572 search-agent > 58358 [PSH, ACK] Seq=4752622 Ack=1741 Win=66048 Len=506 TSval=2951472 TSecr=2921060 
**5196 28.068422 10.200.252.2   10.200.252.1   TCP  66  58358 > search-agent [ACK] Seq=1741 Ack=4742514 Win=64512 Len=0 TSval=2921061 TSecr=2951472 
**5197 28.078479 10.200.252.2   10.200.252.1   TCP  66  58358 > search-agent [ACK] Seq=1741 Ack=4753128 Win=64512 Len=0 TSval=2921062 TSecr=2951472 
    5198 28.082418 10.200.252.2   10.200.252.1   TCP  70  58358 > search-agent [PSH, ACK] Seq=1741 Ack=4753128 Win=64512 Len=4 TSval=2921062 TSecr=2951472 
    5199 28.082675 10.200.252.2   10.200.252.1   TCP  68  58358 > search-agent [PSH, ACK] Seq=1745 Ack=4753128 Win=64512 Len=2 TSval=2921062 TSecr=2951472 
    5200 28.082714 10.200.252.1   10.200.252.2   TCP  66  search-agent > 58358 [ACK] Seq=4753128 Ack=1747 Win=66048 Len=0 TSval=2951474 

回答

0

擺脫分塊和應用的ACK乾脆。如果必須的話,只需在文件末尾有一個最後一個。 TCP已經做了分塊和確認,並且你正在把它搞瘋了,例如它必須確認ACK。沒有必要這麼複雜。這是一個流媒體協議:像一個一樣使用它。

+0

該協議不是我的改變。我必須使用它 – krusty

+0

即使它會大大提高所有平臺的吞吐量? – EJP

+0

不幸的是。我無法訪問服務器或協議。 – krusty