Geringe Leistung tritt auf, wenn Sie Daten mit einem Programm für Windows Sockets-API in ein TCP-Server kopieren

Gilt für: Microsoft Windows Server 2003 Enterprise Edition (32-bit x86)Microsoft Windows Server 2003 Standard Edition (32-bit x86)Microsoft Windows Server 2003 Web Edition

Problembeschreibung


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

Nehmen Sie einen Netzwerk-Trace mit einem Netzwerksniffer wie Microsoft Netzwerkmonitor, sendet der Server TCP TCP ACK segment im TCP-Segment in einen TCP-Datenstrom in der Zeitgeber für verzögerte Bestätigung (auch bekannt als der Zeitgeber für verzögerte Bestätigung). Der Wert dieser Zeitgeber ist standardmäßig für Windows 200 Millisekunden (ms). Normalen Datenfluss zum Senden von Daten in 64 Kilobyte (KB) ähnelt der folgenden Reihenfolge:
Client->Server 1460 bytesClient->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



Ursache


Dieses Problem tritt wegen der Architektur der Windows Sockets-API und Afd.sys. Dieses Problem tritt auf, wenn alle folgenden Punkte zutreffen:

  • Windows Sockets verwendet, nicht blockierende Sockets.
  • Einzelne Senden anrufen oder WSASend Aufruf füllt die gesamte zugrunde liegende Socket Sendepuffer.

    Beispielsweise verwendet die Anwendung die Windows Sockets Setsockopt -Funktion Standard Socket gesendete Puffer auf 32 KB bei der Socket Initialisierungsroutinen ändern:
    setsockopt( sock, SOL_SOCKET, 32768, (char *) &val, sizeof( int ) );
    Später, wenn die Anwendung Daten sendet, gibt einen Aufruf Senden oder einen Anruf WSASend und 64 KB an Daten während jeder senden sendet:
    send(socket, pWrBuffer, 65536, 0);
    In diesem Szenario bei jedem Programm Probleme ein Senden von 64 KB Daten aufrufen das Programm SOCKET_ERROR gibt einen Fehlercode zurück zugrunde liegenden Socket 32 KB Puffer vollständig ausgefüllt ist. Nachdem sie die Funktion WSAGetLastError aufruft, empfängt das Programm den Fehlercode WSAEWOULDBLOCK . Die meisten Programme Funktion Windows Sockets Wählen Sie den Status des Sockets überprüft. In diesem Szenario meldet Function auswählen nicht Socket Schreibschutz an, bis der Client das ausstehende TCP ACK-Segment empfängt. Standardmäßig in einer Windows-Umgebung kann dies 200 ms aufgrund der verzögerten Bestätigung Algorithmus dauern.
  • TCP-Remoteserver bestätigt die TCP-Segmente, bevor der Client das letzte TCP-Segment mit dem Push sendet.

PROBLEMUMGEHUNG


Um dieses Problem zu umgehen, verwenden Sie eine der folgenden Methoden.

Methode 1: Verwenden von Sockets blockieren

Dieses Problem tritt nur bei nicht-blockierende Sockets. Wenn Sie ein blockierendes Socket verwenden, tritt dieses Problem nicht da Afd.sys Socket Puffer anders behandelt. Weitere Informationen über blockierende und nicht blockierende Sockets Programmierung finden Sie in der Microsoft Platform SDK-Dokumentation.

Methode 2: Machen Sie Socket sendet Puffergröße übersteigt die Puffergröße Programm senden

Ändern der Socket Sendepuffer Funktion Windows Sockets Getsockopt bestimmen die Steckdose senden Puffergröße (SO_SNDBUF) und Setsockopt -Funktion den Socket festzulegende Puffergröße senden. Wenn Sie fertig sind, muss der Wert SO_SNDBUF mindestens 1 Byte größer als Programm sendet Puffergröße sein.

Ändern Sie den Aufruf Senden oder WSASend Aufruf an einen Puffer kleiner als der Wert des SO_SNDBUF mindestens 1 Byte Größe. Im Beispiel oben im Abschnitt "Ursache" dieses Artikels können Sie Setsockopt Aufruf auf folgenden Wert ändern,
setsockopt( sock, SOL_SOCKET, 65537, (char *) &val, sizeof( int ) );
oder könnte den Aufruf Senden den folgenden Wert ändern:
send(socket, pWrBuffer, 32767, 0);
Sie können auch eine beliebige Kombination dieser Werte.

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

Wichtig Dieser Abschnitt bzw. die Methode oder Aufgabe enthält Schritte, die erklären, wie Sie die Registrierung ändern. Allerdings können schwerwiegende Probleme auftreten, wenn Sie die Registrierung falsch ändern. Stellen Sie daher sicher, dass Sie die folgenden Schritte sorgfältig ausführen. Sichern Sie die Registry für zusätzlichen Schutz, bevor Sie sie ändern. Anschließend können Sie die Registrierung wiederherstellen, falls ein Problem auftritt. Weitere Informationen zum Sichern und Wiederherstellen der Registrierung finden Sie im folgenden Artikel der Microsoft Knowledge Base:
322756 zum Sichern und Wiederherstellen der Registrierung in Windows


Ändern Sie die TCP/IP-Einstellungen TCP-Server eingehende TCP-Segmente sofort bestätigen. Diese Methode funktioniert am besten eine große Clientinstallation Basis hat und Sie können nicht das Verhalten des Programms ändern. Für Szenarien dem TCP-Remoteserver auf einem Windows-Server ausgeführt wird, müssen Sie die Registrierung des remote-Servers ändern. Für andere Betriebssysteme Dokumentation des Betriebssystems Informationen den Zeitgeber für verzögerte Bestätigung ändern.

Gehen Sie auf einem Server, der Windows 2000 ausgeführt wird folgendermaßen vor:
  1. Registrierungseditor (Regedit.exe) zu starten.
  2. Suchen Sie den folgenden Registrierungsunterschlüssel, und klicken Sie dann darauf:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\ < Schnittstelle GUID >
  3. Klicken Sie im Menü Bearbeiten auf Wert hinzufügen, und erstellen Sie den folgenden Registrierungswert:

    Wertname: TcpDelAckTicks
    Datentyp: REG_DWORD
    Wert: 0
  4. Beenden Sie den Registrierungseditor.
  5. Starten Sie Windows für diese Änderung wirksam wird.
Folgendermaßen Sie auf einem Server, der Windows XP ausführt oder Windows Server 2003 vor:
  1. Starten Sie den Registrierungs-Editor.
  2. Suchen Sie den folgenden Registrierungsunterschlüssel, und klicken Sie dann darauf:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\ < Schnittstelle GUID >
  3. Zeigen Sie im Menü Bearbeiten auf Neu, und klicken Sie dann auf DWORD-Wert.
  4. Benennen Sie den neuen Wert TcpAckFrequency, und weisen Sie ihm den Wert 1.
  5. Beenden Sie den Registrierungseditor.
  6. Starten Sie Windows für diese Änderung wirksam wird.

Methode 4: Ändern des Pufferung Verhaltens in Afd.sys für nicht-blockierende sockets

Wichtig Dieser Abschnitt bzw. die Methode oder Aufgabe enthält Schritte, die erklären, wie Sie die Registrierung ändern. Allerdings können schwerwiegende Probleme auftreten, wenn Sie die Registrierung falsch ändern. Stellen Sie daher sicher, dass Sie die folgenden Schritte sorgfältig ausführen. Sichern Sie die Registry für zusätzlichen Schutz, bevor Sie sie ändern. Anschließend können Sie die Registrierung wiederherstellen, falls ein Problem auftritt. Weitere Informationen zum Sichern und Wiederherstellen der Registrierung finden Sie im folgenden Artikel der Microsoft Knowledge Base:
322756 zum Sichern und Wiederherstellen der Registrierung in Windows


Hinweis Dieser Registrierungsschlüssel ist nur für Windows Server 2003 mit Service Pack 1 und nachfolgenden Servicepacks.
  1. Klicken Sie auf Start, geben Sie regedit.exeund klicken Sie dann auf OK.
  2. Suchen Sie den folgenden Registrierungsunterschlüssel, und klicken Sie dann darauf:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters
  3. Zeigen Sie im Menü Bearbeiten auf Neu, und klicken Sie dann auf DWORD-Wert.
  4. Benennen Sie den Wert NonBlockingSendSpecialBufferingund weisen Sie ihm den Wert 1.
  5. Registrierungseditor beenden.
  6. Starten Sie Windows für diese Änderung wirksam wird.

Status


Microsoft hat bestätigt, dass es sich um ein Problem bei den Microsoft-Produkten handelt, die im Abschnitt „Eigenschaften“ aufgeführt sind.

Referenzen


328890 neuer Registrierungseintrag zum Steuern des Verhaltens TCP-Bestätigung (ACK) in Windows XP und Windows Server 2003