2

サーバーからクライアントを切断しようとしていますが、サーバーはまだ接続されていると認識しています。これに対する解決策が見つからず、シャットダウン、切断、およびクローズがすべて機能しません。

クライアントから切断してサーバーをチェックするためのコード:

クライアント:

  private void btnDisconnect_Click(object sender, EventArgs e)
    {
        connTemp.Client.Shutdown(SocketShutdown.Both);
        connTemp.Client.Disconnect(false);
        connTemp.GetStream().Close();
        connTemp.Close();
    }

サーバ:

    while (client != null && client.Connected)
            {
                NetworkStream stream = client.GetStream();
                data = null;

                try
                {
                    if (stream.DataAvailable)
                    {
                        data = ReadStringFromClient(client, stream);
                        WriteToConsole("Received Command: " + data);
                    }
                } // So on and so on...

コードのさらに下の方に、さらに書き込みと読み取りがあります。

皆様のお役に立てれば幸いです。

更新:スコープの問題があり、client.Connectedが読み取り後もtrueのままであると仮定して、refでTCPクライアントを渡そうとしました。何がうまくいかないのですか?

2回目の更新!!:

これが解決策です。のぞいてみて、それに基づいて、接続されているかどうかを判断します。

  if (client.Client.Poll(0, SelectMode.SelectRead))
                    {
                        byte[] checkConn = new byte[1];
                        if (client.Client.Receive(checkConn, SocketFlags.Peek) == 0)
                        {
                            throw new IOException();
                        }
                    }
4

4 に答える 4

7

これが解決策です!!

  if (client.Client.Poll(0, SelectMode.SelectRead))
                {
                    byte[] checkConn = new byte[1];
                    if (client.Client.Receive(checkConn, SocketFlags.Peek) == 0)
                    {
                        throw new IOException();
                    }
                }
于 2010-09-24T16:39:40.213 に答える
1

MSDN ドキュメントから:

Connected プロパティは、最後の I/O 操作の時点でのクライアント ソケットの接続状態を取得します。

false が返された場合、クライアント ソケットは接続されていなかったか、接続されていません。Connected プロパティは、最新の操作の時点での接続の状態のみを反映するため、現在の状態を判断するには、メッセージの送受信を試みる必要があります。メッセージの送信が失敗すると、このプロパティは true を返さなくなります。この動作は仕様によるものであることに注意してください。テストと送受信の間に接続が失われた可能性があるため、接続の状態を確実にテストすることはできません。コードは、ソケットが接続されていると想定し、失敗した送信を適切に処理する必要があります。

于 2010-09-23T21:00:26.693 に答える
1

NetworkStream クラスについてはよくわかりませんが、主にラッパー クラスであるため、Socket クラスと同様に動作すると思います。一般に、サーバーは、ソケットで I/O 操作 (読み取りまたは書き込み) を実行しない限り、クライアントがソケットから切断されたことを認識しません。ただし、ソケットで BeginRead を呼び出すと、ソケットから読み取るデータが存在するまでコールバックは呼び出されないため、EndRead を呼び出してバイト読み取りの戻り値 0 (ゼロ) を取得すると、ソケットが切断されたことを意味します。Read を使用して 0 バイトの読み取り結果を取得した場合、基になる Socket クラスの Connected プロパティを確認できると思われます。ソケットで I/O 操作が実行されたためにクライアントが切断された場合は false になります。

于 2010-09-23T21:21:35.277 に答える
0

これは一般的な TCP の問題です。以下を参照してください。

この回避策は、プロトコルの一部として期待される量のデータを送信することに依存する傾向があります。これは、HTTP 1.1 がContent-Length(エンティティ全体に対して) ヘッダーを使用するか、チャンク転送エンコーディング (さまざまなチャンク サイズ) を使用して行うことです。

もう 1 つの方法は、プロトコルの一部として定期的に「NOOP」または同様のコマンド (基本的に何もしないが、通信がまだ開いていることを確認するメッセージ) を送信することです。

(クライアントがサーバーに送信して接続をきれいに閉じるコマンドをプロトコルに追加することもできますが、それを取得できないからといって、クライアントが切断されていないということにはなりません。)

于 2010-09-23T21:15:06.067 に答える