1

同じコンピューターで実行されている別のTcpClientに非常に小さなデータ(日付)を送信する際に問題が発生します。

以下のコードでは、NetworkStreamを閉じる前にスリープしていることがわかります。削除するSleepと、データがもう一方の端に表示されないという断続的な問題が発生します。

私はここで何か間違ったことをしていますか?

using (TcpClient client = new TcpClient())
{
    client.Connect(new IPEndPoint(IPAddress.Loopback, _tcpServerPort));
    NetworkStream clientStream = client.GetStream();

    byte[] buffer = new ASCIIEncoding().GetBytes(theDateObject.ToString("yyyy-MM-dd HH:mm:ss"));                            
    clientStream.Write(buffer, 0, buffer.Length);
    clientStream.Flush();
    System.Threading.Thread.Sleep(1000); // Remove this line and the data may not arrive at the other end
    clientStream.Close();
}

その他の情報:

  • 一部のコンピューターでは、問題を引き起こさずに削除できますSleep(遅いコンピューターですか?)
  • (スリープする代わりに)でNetworkStreamを閉じようとしましたClose(int timeout)が、役に立ちませんでした。
  • 1000ミリ秒の値は任意です。他の値でも機能すると思います。問題は、そもそもなぜそれが必要なのかということです。
4

2 に答える 2

1

NetworkStream でタイムアウトを指定して close を呼び出すと、ネットワーク ストリームがバックグラウンドで X 時間開いたままになり、残りのデータを送信できるようになります。コードはこれによってブロックされないため、バックグラウンドで注意することが重要です。tcpClient を using ステートメントでカプセル化するため、クライアントと内部の NetworkStream は、close の呼び出しの直後に破棄されます。この場合のスリープは、データの送信を許可し、その間メソッドをブロックして、リソースが強制的に破棄されるのを防ぐため、機能します。

よりクリーンな解決策は、TcpClient でアクティブな LingerState を十分に長いタイムアウトで設定することです。参照: http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.lingerstate.aspx

于 2012-10-19T08:15:18.023 に答える
0

受信キューが空でない場合 (サーバーから受信バッファにまだ読み取っていないデータを取得した場合、ソケット (クライアント) を破棄すると TCP RST (接続をリセット) が送信されます) で、送信バッファ内のデータは破棄されます。つまり、まだ送信されていない場合は失われます。それ以外の場合は、送信バッファーが空になるまで待機してから、tcp 接続を終了します。

1 つの回避策は、送信チャネルを閉じることです。

    client.Client.Shutdown(SocketShutdown.Send)
    clientStream.Close();
}

(thread.sleep の代わりに) クライアントを閉じる前に、この場合、接続はリセットされません。

また、 .Flush() はネットワークストリームでは何もしません。

参照: http://cs.baylor.edu/~donahoo/practical/JavaSockets/RecvQClose.pdf

于 2012-11-05T15:11:39.110 に答える