私はWSARecv()
どちらが戻ったかを呼び出しましたWSA_IO_PENDING
。次にRST
、もう一方の端からパケットを送信しました。GetQueuedCompletionStatus()
別のスレッドに存在する関数が戻ってきたFALSE
予想通り、私は呼ばれたときWSAGetLastError()
、私は得た64
代わりにWSAECONNRESET
。
では、なぜWSAGetLastError()
戻ってこなかったのWSAECONNRESET
ですか?
編集:
(パケットが受信されたために)WSAGetLastError()
失敗した直後に呼び出すと、返されるエラーコードはであり、ではないことを忘れました。WSARecv()
RST
WSAECONNRESET
64
したがって、返されるエラーコードはWSARecv()
、呼び出し直後に失敗したか、後で完了パケットを取得するときに失敗したかによって異なるようです。
これはIOCPの一般的な問題であり、TCP / IPドライバースタックに対して低レベルの呼び出しを行っています。これは、すべてのドライバーがWindowsで行うように、NTSTATUSエラーコードで失敗を報告します。ここで予想されるエラーはSTATUS_CONNECTION_RESETです。
これらのネイティブエラーコードは、winapiエラーコードに変換する必要があります。この変換は通常、状況依存であり、どのwinapiライブラリがドライバーコマンドを発行したかによって異なります。つまり、変換を行ったのがWinsockライブラリである場合にのみ、WSAECONNRESETエラーを返すことができます。しかし、それはあなたのプログラムで起こったことではなく、エラーを処理したのはGetQueuedCompletionStatus()でした。
これは、任意のデバイスドライバーのIOCPを処理する汎用ヘルパー関数です。コンテキストはありません。OVERLAPPED構造は、I / O要求がどのように開始されたかを示すのにほぼ十分ではありません。回し、このKBの記事、それはWINAPIエラーコードにNTSTATUSエラーコードからデフォルトのマッピングを説明しています。GetQueuedCompletionStatus()が使用するマッピング。リストの関連エントリは次のとおりです。
STATUS_NETWORK_NAME_DELETED ERROR_NETNAME_DELETED
STATUS_LOCAL_DISCONNECT ERROR_NETNAME_DELETED
STATUS_REMOTE_DISCONNECT ERROR_NETNAME_DELETED
STATUS_ADDRESS_CLOSED ERROR_NETNAME_DELETED
STATUS_CONNECTION_DISCONNECTED ERROR_NETNAME_DELETED
STATUS_CONNECTION_RESET ERROR_NETNAME_DELETED
これらは、ええと、素晴らしい選択ではありませんでした。おそらく、Lanmanが選択されたネットワーク層であった非常に初期のWindowsに戻ります。WSAGetLastError()は、ERROR_NETNAME_DELETEDをWSA固有のエラーにマップするのに非常に無力です。GetQueuedCompletionStatus()がスレッドの「最後のエラー」コードを設定すると、NTSTATUSコードが失われました。したがって、そうではなく、可能なものを返すだけです。
何がしたい期待することは、このエラーの翻訳は、Winsockの規則を使用して、正確に起こることができるようにWSAGetQueuedCompletionStatus()関数です。ありません。最近では、Windowsコードを適切に作成するための最終的な権限、つまりリファレンスソースから入手できる.NETFrameworkソースを使用することを好みます。SocketAsyncEventArgs.CompletionCallback()メソッドのソースにリンクしました。キーが含まれています:
// The Async IO completed with a failure.
// here we need to call WSAGetOverlappedResult() just so Marshal.GetLastWin32Error() will return the correct error.
bool success = UnsafeNclNativeMethods.OSSOCK.WSAGetOverlappedResult(
m_CurrentSocket.SafeHandle,
m_PtrNativeOverlapped,
out numBytes,
false,
out socketFlags);
socketError = (SocketError)Marshal.GetLastWin32Error();
つまり、GetLastError()から適切な戻り値を取得するには、WSAGetOverlappedResult()を追加で呼び出す必要があります。これはあまり直感的ではありません:)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加