Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieser Artikel enthält Problemumgehungen für das Problem, bei dem langsame Leistung auftritt, wenn Sie Daten mithilfe eines Windows Sockets-API-Programms auf einen TCP-Server kopieren.
Ursprüngliche KB-Nummer: 823764
Symptome
Wenn Sie ein Programm ausführen, das die Windows Sockets-API verwendet, tritt möglicherweise eine langsame Leistung auf, wenn Sie Daten auf einen TCP-Server kopieren.
Wenn Sie eine Netzwerkablaufverfolgung mit einem Netzwerksniffer wie Microsoft Network Monitor vornehmen, 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). Für Windows-Betriebssysteme beträgt der Wert für diesen Timer standardmäßig 200 Millisekunden (ms). Ein typischer Datenfluss für das Senden von 64 KB (KB) von Daten ähnelt der folgenden Sequenz:
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 Byte
-> verzögert 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 Socket-Sendepuffer aus.
Das Programm verwendet beispielsweise die Windows Sockets-Funktion, um den Standard-Socket-Sendepuffer während der Socketinitialisierungsroutinen
setsockopt
auf 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-Anruf aus und sendet während jeder Übermittlung 64 KB Daten:
send(socket, pWrBuffer, 65536, 0);
In diesem Szenario gibt das Programm jedes Mal, wenn das Programm einen Sendeaufruf von 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 den Status des Sockets zu überprüfen. In diesem Szenario meldet die Auswahlfunktion den Socket erst dann 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 200 ms dauern.
Der Remote-TCP-Server erkennt alle TCP-Segmente an, bevor der Client das letzte TCP-Segment mit dem Pushbitsatz sendet.
Problemumgehung
Verwenden Sie eine der folgenden Methoden, um dieses Problem zu umgehen.
Methode 1: Verwenden von blockierenden Sockets
Dieses Problem tritt nur bei nicht blockierenden Sockets auf. Wenn Sie einen Blockierungssocket verwenden, tritt dieses Problem nicht auf, da afd.sys den Socketpuffer unterschiedlich behandelt. Weitere Informationen zur Blockierung und nicht blockierenden Socketprogrammierung finden Sie in der Dokumentation zum Microsoft Platform SDK.
Methode 2: Festlegen der Puffergröße für das Senden des Sockets über die Größe des Sendepuffers des Programms
Verwenden Sie zum Ändern des Sockets-Sendepuffers die Windows Sockets-Funktion getsockopt
, um die größe des aktuellen Sockets-Sendepuffers (SO_SNDBUF) zu bestimmen, und verwenden Sie dann die setsockopt
Funktion, um die Socket-Sendepuffergröße festzulegen. Wenn Sie fertig sind, muss der SO_SNDBUF Wert mindestens 1 Byte größer sein als die Größe des Programm-Sendepuffers.
Ändern Sie den Sendeaufruf oder den WSASend-Aufruf, um eine Puffergröße mindestens 1 Byte anzugeben, die kleiner als der SO_SNDBUF Wert ist. Im vorherigen Beispiel im Abschnitt "Ursache" dieses Artikels können Sie den setockopt-Aufruf auf den folgenden Wert ändern:
setsockopt( sock, SOL_SOCKET, 65537, (char *) &val, sizeof( int ));
oder Sie können den Sendeanruf an 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 müssen Sie sicherstellen, dass Sie diese Schritte sorgfältig ausführen. Für weiteren 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 und wo Sie das Verhalten des Programms nicht ändern können. Für Szenarien, in denen der Remote-TCP-Server auf einem Windows-basierten Server ausgeführt wird, müssen Sie die Registrierung des Remoteservers ändern. Weitere Informationen zum Ändern des verzögerten Bestätigungszeitgebers finden Sie in der Dokumentation des Betriebssystems.
Führen Sie auf einem Server mit Windows 2000 die folgenden Schritte aus:
- Starten Sie den Registrierungs-Editor (Regedit.exe).
- Finden und klicken Sie auf den folgenden Registrierungsunterschlüssel:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
- Klicken Sie im Menü "Bearbeiten " auf "Wert hinzufügen", und erstellen Sie dann den folgenden Registrierungswert:
Wertname: TcpDelAckTicks
Datentyp: REG_DWORD
Wertdaten: 0 - Schließen Sie den Registrierungs-Editor.
- 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:
- Starten Sie den Registrierungs-Editor.
- Finden und klicken Sie auf den folgenden Registrierungsunterschlüssel:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
- Zeigen Sie im Menü Bearbeiten auf Neu, und klicken Sie anschließend auf DWORD-Wert.
- Nennen Sie den neuen Wert TcpAckFrequency, und weisen Sie ihn dem Wert 1 zu.
- Schließen Sie den Registrierungs-Editor.
- 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 müssen Sie sicherstellen, dass Sie diese Schritte sorgfältig ausführen. Für weiteren Schutz sichern Sie die Registrierung, bevor Sie sie ändern. Anschließend können Sie die Registrierung wiederherstellen, wenn ein Problem auftritt. Weitere Informationen zum Sichern und Wiederherstellen der Registrierung finden Sie in der Microsoft Knowledge Base auf der folgenden Artikelnummer: 322756 Sichern und Wiederherstellen der Registrierung in Windows
Notiz
Dieser Registrierungsschlüssel ist nur für Windows Server 2003 mit Service Pack 1 und nachfolgenden Service Packs verfügbar.
- Klicken Sie auf "Start", geben Sie regedit.exe ein, und klicken Sie dann auf "OK".
- Klicken Sie auf den folgenden Registrierungsunterschlüssel:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters
- Zeigen Sie im Menü Bearbeiten auf Neu, und klicken Sie anschließend auf DWORD-Wert.
- Nennen Sie den neuen Wert NonBlockingSendSpecialBuffering, und weisen Sie ihn dem Wert 1 zu.
- Beenden Sie den Registrierungs-Editor.
- 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 ACK-Verhaltens (TCP-Bestätigung) in Windows XP und windows Server 2003