Langsame Leistung tritt auf, wenn Sie Daten mithilfe eines Windows Sockets-API-Programms auf einen TCP-Server kopieren.

Dieser Artikel enthält Problemumgehungen für das Problem, dass beim Kopieren von Daten auf einen TCP-Server mit einem Windows Sockets-API-Programm eine langsame Leistung auftritt.

Gilt für: Windows Server 2012 R2, Windows 10 – alle Editionen
Ursprüngliche KB-Nummer: 823764

Symptome

Wenn Sie ein Programm ausführen, das die Windows Sockets-API verwendet, tritt beim Kopieren von Daten auf einen TCP-Server möglicherweise eine langsame Leistung auf.

Wenn Sie eine Netzwerkablaufverfolgung mit einem Netzwerk-Sniffer wie Microsoft Network Monitor erstellen, sendet der TCP-Server ein TCP-ACK-Segment an das letzte TCP-Segment in einem TCP-Datenstrom im Verzögerten Bestätigungszeitgeber (auch bekannt als verzögerter ACK-Timer). Bei Windows-Betriebssystemen beträgt der Wert für diesen Timer standardmäßig 200 Millisekunden (ms). Ein typischer Datenfluss zum Senden von Daten mit 64 KB sieht in etwa wie folgt aus:

Client-Server> 1460 Byte
Client-Server> 1460 Byte
Server-Client-ACK>
Client-Server> 1460 Byte
Client-Server> 1460 Byte
Server-Client-ACK>
....
Client-Server> 1460 Byte
Client-Server> 1460 Byte
Server-Client> ACK-PUSH
Client-Server> 1296 Byte
-> verzögerte ACK 200 ms

Ursache

Dieses Problem tritt aufgrund des Architekturverhaltens der Windows Sockets-API und afd.sys auf. Dieses Problem tritt auf, wenn alle folgenden Bedingungen erfüllt sind:

  • Das Windows Sockets-Programm verwendet nicht blockierende Sockets.

  • Ein einzelner Sendeaufruf oder WSASend-Aufruf füllt den gesamten zugrunde liegenden Sockets-Sendepuffer aus.

    Beispielsweise verwendet das Programm die Windows Sockets-Funktion setsockopt , um den Standardmäßigen Sockets-Sendepuffer während der Socketinitialisierungsroutinen in 32 KB zu ändern:

    setsockopt( sock, SOL_SOCKET, 32768, (char *) &val, sizeof( int ));
    

    Wenn das Programm später Daten sendet, gibt es einen Sendeanruf oder einen WSASend-Aufruf aus und sendet 64 KB Daten während jedes Sendevorgangs:

    send(socket, pWrBuffer, 65536, 0);
    

    In diesem Szenario gibt das Programm jedes Mal, wenn das Programm einen Sendeaufruf mit 64 KB Daten ausgibt, einen SOCKET_ERROR Fehlercode zurück, wenn der zugrunde liegende 32-KB-Socketpuffer gefüllt ist. Nachdem die WSAGetLastError-Funktion aufgerufen wurde, empfängt das Programm den WSAEWOULDBLOCK-Fehlercode. Die meisten Programme verwenden die Windows Sockets-Auswahlfunktion, um die status des Sockets zu überprüfen. In diesem Szenario meldet die Select-Funktion den Socket erst als schreibbar, wenn der Client das ausstehende TCP-ACK-Segment empfängt. In einer Windows-Umgebung kann dies aufgrund des Verzögerten Bestätigungsalgorithmus standardmäßig bis zu 200 ms dauern.

  • Der TCP-Remoteserver bestätigt alle TCP-Segmente, bevor der Client das letzte TCP-Segment mit festgelegtem Pushbit sendet.

Problemumgehung

Verwenden Sie eine der folgenden Methoden, um dieses Problem zu umgehen.

Methode 1: Blockierende Sockets verwenden

Dieses Problem tritt nur bei nicht blockierenden Sockets auf. Wenn Sie einen blockierenden Socket verwenden, tritt dieses Problem nicht auf, da afd.sys den Socketpuffer unterschiedlich behandelt. Weitere Informationen zum Blockieren und nicht blockierenden Socketprogramm finden Sie in der Dokumentation zum Microsoft Platform SDK.

Methode 2: Größe des Sockets-Sendepuffers größer als die Größe des Programm-Sendepuffers

Verwenden Sie zum Ändern des Sockets-Sendepuffers die Windows Sockets-Funktion, um die aktuelle Größe des Sockets-Sendepuffers getsockopt (SO_SNDBUF) zu bestimmen, und verwenden Sie dann die -Funktion, um die setsockopt Größe des Sockets-Sendepuffers festzulegen. Wenn Sie fertig sind, muss der SO_SNDBUF Wert mindestens 1 Byte größer als die Größe des Programm-Sendepuffers sein.

Ändern Sie den Sendeaufruf oder den WSASend-Aufruf, um eine Puffergröße anzugeben, die mindestens 1 Byte kleiner als der SO_SNDBUF Wert ist. Im vorherigen Beispiel im Abschnitt "Ursache" dieses Artikels konnten Sie den setockopt-Aufruf in den folgenden Wert ändern:

setsockopt( sock, SOL_SOCKET, 65537, (char *) &val, sizeof( int ));

Oder Sie können den Send-Aufruf auf den folgenden Wert ändern:

send(socket, pWrBuffer, 32767, 0);

Sie können auch eine beliebige Kombination dieser Werte verwenden.

Methode 3: Ändern der TCP/IP-Einstellungen auf dem TCP-Server

Wichtig

Dieser Abschnitt, diese Methode bzw. diese Aufgabe enthält eine Beschreibung der Schritte zum Bearbeiten der Registrierung. Durch die falsche Bearbeitung der Registrierung können schwerwiegende Probleme verursacht werden. Daher ist es wichtig, bei der Ausführung der folgenden Schritte sorgfältig vorzugehen. Für zusätzlichen Schutz sichern Sie die Registrierung, bevor Sie sie ändern. Sie können die Registrierung wiederherstellen, wenn ein Problem auftritt. Weitere Informationen zum Erstellen und Wiederherstellen einer Sicherungskopie der Registrierung finden Sie im folgenden Artikel der Microsoft Knowledge Base:
322756 Sichern und Wiederherstellen der Registrierung in Windows

Ändern Sie die TCP/IP-Einstellungen auf dem TCP-Server, um eingehende TCP-Segmente sofort zu bestätigen. Diese Problemumgehung funktioniert am besten in einer Umgebung mit einer großen Clientinstallationsbasis, in der Sie das Verhalten des Programms nicht ändern können. In Szenarien, in denen der TCP-Remoteserver auf einem Windows-basierten Server ausgeführt wird, müssen Sie die Registrierung des Remoteservers ändern. Informationen zum Ändern des Timers für verzögerte Bestätigungen finden Sie in der Dokumentation des Betriebssystems.

Führen Sie auf einem Server, auf dem Windows 2000 ausgeführt wird, die folgenden Schritte aus:

  1. Starten Sie Editor (Regedit.exe).
  2. Finden und klicken Sie auf den folgenden Registrierungsunterschlüssel: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
  3. Klicken Sie im Menü Bearbeiten auf Wert hinzufügen, und erstellen Sie dann den folgenden Registrierungswert:
    Wertname: TcpDelAckTicks
    Datentyp: REG_DWORD
    Wertdaten: 0
  4. Schließen Sie den Registrierungs-Editor.
  5. Starten Sie Windows neu, damit diese Änderung wirksam wird.

Führen Sie auf einem Server mit Windows XP oder Windows Server 2003 die folgenden Schritte aus:

  1. Starten Sie den Registrierungs-Editor.
  2. Finden und klicken Sie auf den folgenden Registrierungsunterschlüssel: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
  3. Zeigen Sie im Menü Bearbeiten auf Neu, und klicken Sie anschließend auf DWORD-Wert.
  4. Nennen Sie den neuen Wert TcpAckFrequency, und weisen Sie ihm den Wert 1 zu.
  5. Schließen Sie den Registrierungs-Editor.
  6. Starten Sie Windows neu, damit diese Änderung wirksam wird.

Methode 4: Ändern des Pufferverhaltens in afd.sys für nicht blockierende Sockets

Wichtig

Dieser Abschnitt, diese Methode bzw. diese Aufgabe enthält eine Beschreibung der Schritte zum Bearbeiten der Registrierung. Durch die falsche Bearbeitung der Registrierung können schwerwiegende Probleme verursacht werden. Daher ist es wichtig, bei der Ausführung der folgenden Schritte sorgfältig vorzugehen. Für zusätzlichen Schutz sichern Sie die Registrierung, bevor Sie sie ändern. Sie können die Registrierung wiederherstellen, wenn ein Problem auftritt. Weitere Informationen zum Sichern und Wiederherstellen der Registrierung finden Sie im folgenden Artikel der Microsoft Knowledge Base: 322756 Sichern und Wiederherstellen der Registrierung unter Windows.

Hinweis

Dieser Registrierungsschlüssel ist nur für Windows Server 2003 mit Service Pack 1 und nachfolgenden Service Packs verfügbar.

  1. Klicken Sie auf Start, geben Sieregedit.exeein, und klicken Sie dann auf OK.
  2. Klicken Sie auf den folgenden Registrierungsunterschlüssel:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters
  3. Zeigen Sie im Menü Bearbeiten auf Neu, und klicken Sie anschließend auf DWORD-Wert.
  4. Nennen Sie den neuen Wert NonBlockingSendSpecialBuffering, und weisen Sie ihm den Wert 1 zu.
  5. Beenden Sie die Registrierung Editor.
  6. Starten Sie Windows neu, damit diese Änderung wirksam wird.

Status

Microsoft hat bestätigt, dass es sich hierbei um ein Problem bei den in diesem Artikel genannten Microsoft-Produkten handelt.

References

328890 Neuer Registrierungseintrag zum Steuern des TCP-Bestätigungsverhaltens (ACK) in Windows XP und Windows Server 2003