Tcp

為什麼當客戶端有足夠的視窗可用時 TCP 伺服器等待 ACK

  • October 8, 2019

我在伺服器應用程序和執行在兩台不同 Red Hat 機器上的客戶端之間的 TCP 連接中觀察到以下行為。

範例 1

  1. 到目前為止,客戶端確認所有內容(ACK 與 WND = 1424)

  2. 伺服器向 TCP 層發送 296 個字節並發送給客戶端(PUSH/ACK)

  3. 伺服器向 TCP 層發送 296 個字節並發送給客戶端(PUSH/ACK)

  4. 伺服器向 TCP 層發送 296 個字節並發送給客戶端(PUSH/ACK)

  5. 伺服器發送/嘗試向 TCP 層發送 239 個字節,但是:發生以下兩種情況之一

  6. 在發送這些字節之前,作業系統會等待大約 30 毫秒,直到收到來自客戶端的 ACK(這 x 字節發送將在下面被稱為延遲消息)

  7. tcp 發送呼叫返回 EWOULDBLOUCK 或 EAGAIN(我認為這是不可能的,因為 239+239+239+239 < 1424。如果我錯了,請糾正我

範例 2

  1. 到目前為止,客戶端確認所有內容(ACK 與 WND=1424)
  2. 伺服器向 TCP 層發送 239 個字節,然後發送給客戶端
  3. 伺服器發送/嘗試向 TCP 層發送 239 個字節,並且發生上述兩件事之一

我想了解的問題是,當客戶端的視窗大小足夠大時,為什麼伺服器應用程序或作業系統要等到 ACK?這是我可以在作業系統級別調整的東西嗎?我可以強制伺服器發送所有字節直到客戶端的視窗被填滿嗎?

據我了解有兩個可能的原因

  1. 伺服器應用程序不會將“延遲消息”傳遞到 TCP 級別,因為發送系統呼叫返回 EWOULDBLOUCK 或 EAGAIN。
  2. 應用程序確實將消息傳遞給 TCP 層,但作業系統在收到來自客戶端的 ACK 之前不會發送它。

在所有延遲消息的場景中,在延遲消息的 SEND 之前,都會有來自客戶端的 ACK。此外,應用程序的工作邏輯表明它確實將消息傳遞給 TCP 層。

您能否建議我應該在哪里關注此問題的故障排除。

  1. 我可以在客戶端或伺服器端設置一些作業系統級別的設置嗎
  2. 這是應用程序伺服器中的某種故障嗎?
  3. 假設作業系統在消息填滿視窗之前不會返回 EWOULDBLOCK 我錯了嗎

編輯:重複的原因:我不確定問題出在哪裡;網路/作業系統。我添加了其他細節。另外,我需要一個來自 linux 的 TCP 實現的 POV,所以我認為這個問題屬於這裡。

這稱為“延遲 ACK”,這是 TCP 協議的工作方式。有關詳細資訊,請參閱https://en.m.wikipedia.org/wiki/TCP_delayed_acknowledgment 。如果它影響應用程序的性能,您可以禁用此功能。假設 iSCSI 預設關閉延遲 ACK。

引用自:https://serverfault.com/questions/986867