2014-04-10 27 views
3

我有一個TCP客戶端不斷向服務器發送數據。客戶端與服務器成功連接後,客戶端會以幾秒鐘的間隔連續發送數據。在linux中閱讀send-q TCP socket的內容

當客戶端和服務器之間的鏈接在發送少量數據後斷開連接後,我才知道TCP根據TCP_retries2中的值重新傳輸了數據,我將此值配置爲8,這樣我在寫入錯誤後100秒。 但send-q中會有一些未確認的數據包。

在關閉此套接字之前,有沒有辦法在程序中讀取send-q中未確認的數據包的內容,或者我應該記住發送數據並在重新連接後重新發送數據?有沒有其他的方式來實現這一點?

回答

1

一旦應用程序將數據提供給TCP,TCP就有責任跟蹤數據包的確認。如果ACK不是即將到來的,它會盡可能地根據RTO算法獲得分組。現在直到收到ACK,數據保存在TCP_SEND_Q中。我不認爲應用程序有任何控制來確定TCP_SEND_Q的當前狀態

//我應該記住發送數據和重新連接後重新發送//

你如何做到這一點?以前的連接狀態不見了,是不是?在客戶端和服務器應用程序保持對離線收到和發送的某些理解之前,您必須重新開始新的連接。

+0

感謝您的回答。目前我沒有任何應用程序級別的確認。我想在我從客戶端收到重新發送time_out錯誤之前發送所有發送100秒的數據。我必須考慮應用程序級別的確認。 – Praveen

-1

它需要兩個探戈。您可以關閉連接的結束,並等待連接的另一端也掉線。反過來認爲三方握手。

在關閉連接並重新打開它之間等待多久?在嘗試使用相同連接信息重新連接之前,您必須至少等待TIME_WAIT。

+0

TCP等待另一端刪除連接,但您的應用程序不會等待。 close()函數是異步的。如果您在客戶端重複使用相同的本地端口,則只需等待TIME_WAIT,並且沒有理由在出站端口號上執行其他Han bozo防火牆規則,因爲它們完全沒有實現,並且呈現應用程序無法實現。而你實際上沒有回答這個問題。 – EJP

1

不,沒有。

如果您需要知道對等應用程序已收到數據,您需要讓對等應用程序通過您的應用程序協議將其確認回您的應用程序,並將任何未確認的數據視爲需要以某種方式從您的應用程序重新發送。這也帶來了交易賤金屬的問題,這樣你就可以再犯有罪不罰。

3

你可以用一個ioctl獲得的SendQ的大小:

SIOCOUTQ 
      Returns the amount of unsent data in the socket send queue. 
      The socket must not be in LISTEN state, otherwise an error 
      (EINVAL) is returned. SIOCOUTQ is defined in 
      <linux/sockios.h>. Alternatively, you can use the synonymous 
      TIOCOUTQ, defined in <sys/ioctl.h>. 

注意的SendQ只告訴你什麼是遠程系統的內核接受,但不保證該主機上運行的應用程序來處理它。通信雙方之間的網絡中存在大多數故障,但這一指標不能用作確定的成功傳輸證據。

+0

假設200個字節排隊發送,並且'SIOCOUTQ'返回100,我能確定它是確認的前100個字節,或者可能是最後100個字節,並且第一個丟失了路由嗎? – lvella

+1

TCP是一種流協議,因此只有在接收到該字節的所有內容時才能對字節進行確認,所以可以確定它是前100個字節。 (有一個名爲SACK的TCP擴展,它可以確認接收到任意的數據塊,但這並不會改變tcp結構的snd_una值,所以即使正在使用SACK,我寫的也應該是正確的。) –