完了ポートを使用して非同期 I/O を利用する Windows NT で tcp サーバーを作成しています。TcpSocket クラス、TcpServer クラス、および読み取りが完了したときの onRead() など、I/O 操作が完了したときに呼び出すいくつかの (仮想関数) コールバックがあります。また、接続が確立されたときの onOpen() と、接続が閉じられたときの onEof() などもあります。私は常にソケットの保留中の読み取りを持っているので、ソケットが効果的にデータを取得する場合 (読み取りはサイズ > 0 で完了する)、代わりにクライアントがクライアント側からソケットを閉じる場合(読み取りはサイズ == 0 で完了) onEof() を呼び出し、サーバーはクライアントが closesocket(server_socket); でソケットを閉じるタイミングを認識します。その側から。
すべて正常に動作しますが、次のことに気付きました。
closesocket(client_socket); を呼び出すと、クライアント側ではなく、接続のサーバー側のエンドポイントで (linger {true, 0} を設定するかどうかに関係なく)、保留中の読み取りはエラーとして完了します。つまり、読み取りサイズは == になるだけではありません。 0 だけでなく、GetLastError() もエラーを返します: 64 または 'ERROR_NETNAME_DELETED'。私はこれについてウェブで多くのことを検索しましたが、興味深いものは何も見つかりませんでした。
それから私は自問しました:しかし、これは本当のエラーですか?つまり、これは本当にエラーと見なすことができますか?
問題は、サーバー側では、closesocket(client_socket); のときに onError() コールバックが呼び出されることです。onEof() の代わりに。だから私はこれを考えました:
この「ERROR_NETNAME_DELETED」「エラー」が受信されたときに、 onError() の代わりに onEof() を呼び出すとどうなりますか? それはいくつかのバグや未定義の動作を導入しますか? 私がこの質問をするようになったもう 1 つの重要な点は次のとおりです。
'ERROR_NETNAME_DELETED' でこの読み取り完了を受け取ったときに、OVERLAPPED 構造、特に基礎となるドライバーの NTSTATUS エラー コードを含むoverlapped->Internal パラメーターを確認しました。NTSTATUS エラー コード [ http://www.tenox.tc/links/ntstatus.html ] のリストを見ると、エラーである「ERROR_NETNAME_DELETED」が NTSTATUS 0xC000013B によって生成されていることがはっきりとわかりますが、 「STATUS_LOCAL_DISCONNECT」と呼ばれます。まあ、それはエラーの名前のようには見えません。エラーである「ERROR_IO_PENDING」のように見えますが、正しい動作のステータスでもあります。
では、OVERLAPPED 構造体の Internal パラメータをチェックするとどうなるでしょうか。これが == から 'STATUS_LOCAL_DISCONNECT' の場合、onEof() コールバックの呼び出しが実行されます。物事を台無しにしますか?
さらに、closesocket(client_socket); を呼び出す前に DisconnectEx() を呼び出すと、サーバー側から言う必要があります。そのエラーは表示されません。しかし、 DisconnectEx() を呼び出したくないのはどうですか? たとえば、サーバーがシャットダウンしていて、DisconnectEx() のすべての完了を待機したくないが、接続されているすべてのクライアントを閉じたい場合などです。