3

私は永続的なソケットを持つアプリケーションを持っています (アプリケーションの起動時に開いており、アプリケーションと共に閉じています)。

このソケットは、サーバーがデータをプッシュするために使用されます。

この接続は HTTP または HTTPS のいずれかである可能性があるため、オブジェクトを初期化するために次のコードを記述しました。

s_tcpClient = new TcpClient(s_server.CometIp, s_server.CometPort);
s_tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, false);
s_tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, CST_STREAM_BUFFER_SIZE);
s_tcpClient.ReceiveTimeout = 0;

s_networkStream = s_tcpClient.GetStream();

s_cometStreamReader = null;

if (s_server.Protocol == "HTTPS")
{
    SslStream sslStream = new SslStream(
        s_tcpClient.GetStream(),
        false,
        new RemoteCertificateValidationCallback(ValidateServerCertificate)
    );

    sslStream.AuthenticateAsClient(s_server.CometIp);
    s_cometStreamReader = new StreamReader(sslStream, Encoding.UTF8, true, CST_STREAM_BUFFER_SIZE);
    s_cometStream = sslStream as Stream;
}
else
{
    s_cometStreamReader = new StreamReader(s_networkStream, Encoding.UTF8, true, CST_STREAM_BUFFER_SIZE);
    s_cometStream = s_networkStream as Stream;
}

このようにして、HTTP プロトコルと HTTPS プロトコルの両方を処理できます。

次に、ソケットでデータが利用可能になるのを待つこのループ (スレッド内) を取得しました。

while (s_networkStream.DataAvailable)
{
    numberOfBytesRead = s_cometStream.Read(buffer, 0, buffer.Length);
    message.Append(Encoding.UTF8.GetString(buffer, 0, numberOfBytesRead));
    ExtractMessages(ref message);
}

ここに私の2つの質問があります:

  1. ドキュメントによると、使用可能なデータがない場合、Read メソッドは 0 を返します。しかし、私の場合、Read は 0 より大きい数値を返すか (一部のデータが読み取られた場合)、タイムアウトになったために例外をスローします...ここで何が欠けていますか? Read が 0 を返すのはどのような状況ですか?

  2. 接続が HTTP プロトコルを使用している場合、このコードは正常に機能します。すべてを受信し、メッセージがバッファー サイズ (CST_STREAM_BUFFER_SIZE) よりも大きい場合、DataAvailable は true のままで、ループは残りのデータをすべて読み取ります。しかし、HTTPS でこれを試すと、バッファより小さいメッセージに対してのみ機能します。メッセージが大きい場合、Read メソッドは最初に CST_STREAM_BUFFER_SIZE バイトを読み取り、次に DataAvailable が false になりますが、一部のバイトは明らかに読み取る準備ができています。この場合、別のメッセージを受信すると、DataAvailable が再び true になるため、残りのデータが「スタック解除」されます。私は何を間違っていますか?両方のケースで DataAvailable が同じように動作しないのはなぜですか?

どんな助けでも大歓迎です。

4

1 に答える 1

2

ストリームが閉じている場合にのみ 0 を返すため、それ以上データが来ることはありません。それ以外の場合、データを読み取ることができた場合は正の数であり、データがまだ利用できない場合はブロックを伴う可能性があります。が true の場合、使用可能なデータがない状態で が経過しCanTimeoutた後に操作がスローされReadTimeoutます。

ソケットが開いたままになっているか、会話で複数のデータチャンクを送信するプロトコルを読み込もうとしている可能性があります。

http://msdn.microsoft.com/en-us/library/system.io.stream.readtimeout.aspx

于 2011-02-04T16:21:45.033 に答える