Ich habe WSARecv()
aufgerufen, was WSA_IO_PENDING
zurückgegeben hat. Ich habe dann ein RST
-Paket vom anderen Ende gesendet. Die Funktion GetQueuedCompletionStatus()
, die in einem anderen Thread existiert, hat FALSE
erwartungsgemäß zurückgegeben, aber wenn ich WSAGetLastError()
aufgerufen habe, habe ich 64
anstelle von WSAECONNRESET
.
Also warum WSAGetLastError()
hat WSAECONNRESET
nicht zurückgegeben?
Bearbeiten:
Ich habe vergessen zu erwähnen, dass wenn ich WSAGetLastError()
direkt nach einem fehlgeschlagenen WSARecv()
aufruft (wegen eines empfangenen RST
Pakets), ist der zurückgegebene Fehlercode WSAECONNRESET
und nicht 64
.
Es sieht also so aus, als ob der zurückgegebene Fehlercode davon abhängt, ob WSARecv()
direkt nach dem Aufruf fehlgeschlagen ist oder später beim Abrufen eines Completion-Pakets fehlgeschlagen ist.
Dies ist ein generisches Problem bei IOCP. Sie führen einen Low-Level-Aufruf an den TCP / IP-Treiberstapel durch. Welche, wie alle Treiber in Windows tun, melden Fehler mit NTSTATUS-Fehlercodes. Der erwartete Fehler ist hier STATUS_CONNECTION_RESET.
Diese nativen Fehlercodes müssen in einen winapi-Fehlercode übersetzt werden. Diese Übersetzung ist normalerweise kontextsensitiv , sie hängt davon ab, welche winapi-Bibliothek den Treiberbefehl ausgegeben hat. Mit anderen Worten, Sie können einen WSAECONNRESET-Fehler immer nur dann zurückerhalten, wenn die Winsock-Bibliothek die Übersetzung ausgeführt hat. Aber das ist nicht in Ihrem Programm passiert, es war GetQueuedCompletionStatus (), das den Fehler behandelte.
Dies ist eine generische Hilfsfunktion, die IOCP für jeden Gerätetreiber behandelt. Es gibt keinen Kontext, die OVERLAPPED-Struktur ist nicht annähernd genug, um anzuzeigen, wie die I / O-Anforderung gestartet wurde. Wechseln Sie zu diesem KB-Artikel , es dokumentiert die Standardzuordnung von NTSTATUS-Fehlercodes zu winapi-Fehlercodes. Die Zuordnung, die GetQueuedCompletionStatus () verwendet. Relevante Einträge in der Liste sind:
%Vor%Das waren, ahem, keine fantastischen Entscheidungen. Geht wahrscheinlich auf sehr früh Windows zurück, als Lanman die Netzwerkschicht der Wahl war. WSAGetLastError () ist ziemlich machtlos, ERROR_NETNAME_DELETED einem WSA-spezifischen Fehler zuzuordnen, der NTSTATUS-Code ging verloren, wenn GetQueuedCompletionStatus () den "letzten Fehler" -Code für den Thread festlegte. So ist es nicht, es gibt nur zurück, was es kann.
Was Sie erwarten würden ist eine WSAGetQueuedCompletionStatus () - Funktion, so dass diese Fehlerübersetzung unter Verwendung von Winsock-Regeln korrekt passieren kann. Es gibt keinen. In diesen Tagen verwende ich lieber die ultimative Autorität, um Windows-Code richtig zu schreiben, die .NET Framework-Quelle, wie sie von der Referenzquelle . Ich bin mit der Quelle für die SocketAsyncEventArgs.CompletionCallback () -Methode verbunden. Welche enthält den Schlüssel:
%Vor%Oder mit anderen Worten, Sie müssen einen extra Aufruf an WSAGetOverlappedResult () vornehmen, um den richtigen Rückgabewert von GetLastError () zu erhalten. Das ist nicht sehr intuitiv:)