文章編號: 823764 - 上次校閱: 2007年2月28日 - 版次: 5.6

當您使用 Windows 通訊端 API 程式複製到 TCP 伺服器資料時,就會發生效能變慢

系統提示本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。

在此頁中

全部展開 | 全部摺疊

徵狀

當您執行程式,使用 Windows 通訊端 API 時,您可能會遇到效能變慢,當您將資料複製到 TCP 伺服器。

如果您對網路追蹤與網路 Sniffer 如 Microsoft 網路監視器,TCP 伺服器會傳送 TCP ACK 至最後一個區段中延遲的認可計時器 (也稱為延遲 ACK 計時器) 的 TCP 資料流中的 TCP 區段。Windows 作業系統的預設此計時器值會為 200 毫秒 (ms)。典型的資料流程傳送 64 千位元組 (KB) 的資料看起來類似下列的順序:
Client->Server 1460 bytes
Client->Server 1460 bytes
Server->Client ACK
Client->Server 1460 bytes
Client->Server 1460 bytes
Server->Client ACK
....
Client->Server 1460 bytes
Client->Server 1460 bytes
Server->Client ACK-PUSH
Client->Server 1296 bytes
-> delayed ACK 200 ms


發生的原因

之所以發生這個問題,因為是架構上的 Windows 通訊端 API 和 Afd.sys 行為。如果下列情況成立,就會發生這個問題:
  • Windows 通訊端程式會使用非封鎖通訊端。
  • 傳送 單一呼叫或 WSASend 呼叫填整個基礎的通訊端傳送緩衝區。

    程式使用 Windows 通訊端 setsockopt 函式,在其通訊端初始化常式期間變更預設的通訊端傳送緩衝區為 32 KB 的例如:
    setsockopt( sock, SOL_SOCKET, 32768, (char *) &val, sizeof( int ) );
    稍後時程式會將資料傳送,, 它發出 傳送 呼叫或 WSASend 呼叫並傳送 64 KB 的資料在每個傳送期間:
    send(socket, pWrBuffer, 65536, 0);
    在這種情況程式發出 傳送 呼叫的 64 KB 的資料,每次程式 SOCKET_ERROR 錯誤的程式碼如果傳回基礎 32 KB 通訊端緩衝區會完全填滿。它會呼叫 WSAGetLastError 函式之後程式會接收 WSAEWOULDBLOCK 錯誤的程式碼。大部分的程式使用 Windows 通訊端 選取 函式來檢查通訊端的狀態。在這種情況下 選取 函式不會報告直到用戶端會收到未完成的 TCP ACK 區段為可寫入通訊端。會在 Windows 環境中預設這可能會花 200 毫秒因為的延遲的認可演算法。
  • 用戶端傳送具有發送位元集最後一次的 TCP 區段之前,遠端的 TCP 伺服器會確認所有 TCP 區段。

其他可行方案

如果要解決這個問題,使用下列其中一種方法。

方法 1: 使用封鎖通訊端

非封鎖通訊端只會發生這個問題。當您使用 [封鎖的通訊端這個問題不會發生因為 Afd.sys 以不同方式處理通訊端緩衝區。如需封鎖和非封鎖通訊端程式設計有關的詳細資訊,請參閱 Microsoft 平台 SDK 文件。

方法 2: 讓通訊端傳送緩衝區大小大於程式傳送緩衝區大小

修改通訊端傳送緩衝區、 使用 Windows 通訊端 getsockopt 函式來判斷目前通訊端傳送緩衝區大小 (SO_SNDBUF),然後使用 setsockopt 函式來設定通訊端傳送緩衝區大小。當您完成 SO_SNDBUF 值必須至少 1 個位元組大於程式傳送緩衝區大小。

修改 傳送 呼叫或 WSASend 呼叫指定緩衝區大小至少 1 個位元組小於 SO_SNDBUF 值。在 < 原因 > 一節中本篇文章稍早範例,您可以修改下列值
setsockopt( sock, SOL_SOCKET, 65537, (char *) &val, sizeof( int ) );
或您可以修改 傳送 呼叫至下列值:
send(socket, pWrBuffer, 32767, 0);
您也可以使用這些值的任何組合。

方法 3: 修改 TCP 伺服器上的 [TCP/IP] 設定

重要這個區段、 方法或任務包含告訴您如何修改登錄的步驟。然而,如果您不當修改登錄,可能會發生嚴重的問題。因此,執行這些步驟時請務必小心。為加強保護,修改登錄之前,請務必將它備份起來。以後您就可以在發生問題時還原登錄。如需有關如何備份和還原登錄的詳細資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件:
322756? (http://support.microsoft.com/kb/322756/ ) 如何備份和還原在 Windows 登錄


修改 TCP/IP 設定 TCP 伺服器上的以立即接受連入 TCP 區段。此解決方法最適合在環境中,並且其基底的大型的用戶端安裝,而且您無法在此變更程式的行為。針對案例遠端 TCP 伺服器是在 Windows 架構的伺服器執行的位置,您必須修改遠端伺服器的登錄。對於其他作業系統作業系統的資訊,請參閱說明文件有關如何變更延遲的認可計時器。

在執行 Windows 2000 伺服器上,請依照下列步驟執行:
  1. 啟動 「 登錄編輯程式 」 (Regedit.exe)。
  2. 找出並點選下列登錄子機碼:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
  3. 在 [編輯] 功能表上按一下 新增值],然後再建立下列登錄值:

    數值名稱TcpDelAckTicks
    資料型別REG_DWORD
    數值資料: 0
  4. 結束 「 登錄編輯程式 」。
  5. 重新啟動 Windows,此變更才會生效。
執行 Windows XP 的伺服器或 Windows Server 2003,請依照下列步驟執行:
  1. 啟動 「 登錄編輯程式 」。
  2. 找出並點選下列登錄子機碼:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
  3. 在 [編輯] 功能表上指向 [新增],然後按一下 [DWORD 值]。
  4. 新值 TcpAckFrequency,命名,並將它指派的值是 1。
  5. 結束 「 登錄編輯程式 」。
  6. 重新啟動 Windows,此變更才會生效。

方法 4: 修改 Afd.sys 在非封鎖通訊端的緩衝行為

重要這個區段、 方法或任務包含告訴您如何修改登錄的步驟。然而,如果您不當修改登錄,可能會發生嚴重的問題。因此,執行這些步驟時請務必小心。為加強保護,修改登錄之前,請務必將它備份起來。以後您就可以在發生問題時還原登錄。如需有關如何備份和還原登錄的詳細資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件:
322756? (http://support.microsoft.com/kb/322756/ ) 如何備份和還原在 Windows 登錄


附註 這個登錄機碼才可用的 Service Pack 1 與後續的 Service Pack 的 Windows Server 2003。
  1. 按一下 [開始]、 鍵入 regedit.exe,然後按一下 [確定]
  2. 找出並點選下列登錄子機碼:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters
  3. 在 [編輯] 功能表上指向 [新增],然後按一下 [DWORD 值]。
  4. 新值 NonBlockingSendSpecialBuffering,命名,並將它指派的值是 1。
  5. 結束登錄編輯程式。
  6. 重新啟動 Windows,此變更才會生效。

狀況說明

Microsoft 已確認<適用於>一節所列之 Microsoft 產品確實有此問題。

?考

328890? (http://support.microsoft.com/kb/328890/ ) 對控制 TCP 通知 (ACK) 行為在 Windows XP 和 Windows Server 2003 的新登錄項目

這篇文章中的資訊適用於:
  • Microsoft Windows Server 2003, Enterprise Edition (32-bit x86)
  • Microsoft Windows Server 2003, Standard Edition (32-bit x86)
  • Microsoft Windows Server 2003, Web Edition
  • Microsoft Windows XP Home Edition (家用版)
  • Microsoft Windows XP Professional
  • Microsoft Windows 2000 Advanced Server
  • Microsoft Windows 2000 Professional Edition
  • Microsoft Windows 2000 Server
  • Windows Server 2008 Datacenter without Hyper-V
  • Windows Server 2008 Enterprise without Hyper-V
  • Windows Server 2008 for Itanium-Based Systems
  • Windows Server 2008 Standard without Hyper-V
  • Windows Server 2008 Datacenter
  • Windows Server 2008 Enterprise
  • Windows Server 2008 Standard
  • Windows Web Server 2008
關鍵字:?
kbmt kbprb KB823764 KbMtzh
機器翻譯機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:823764? (http://support.microsoft.com/kb/823764/en-us/ )
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。