5

StreamSocket API を使用してサーバーへのストリーミング接続を行う Windows 8/WinRT 用に作成しているアプリケーションがあります。つまり、サーバーはメタ タグを使用してクライアントにデータをストリーミングし、いつでも切断できます。

私が抱えている問題は、サーバーがいつ切断されたかを検出する方法がわからないことです。入力ストリームまたは出力ストリームのいずれかである StreamSocket クラス、または接続ステータスと関係のある DataReader/DataWriter クラスには、イベントやプロパティはないようです。

その上、サーバー側がクライアントから切断された後、DataReader メソッド ReadAsync は失敗しません。代わりに、私が知る限り、操作は成功し、バッファに書き込まれるデータは、サーバーが最後に送信したものです (つまり、「消費された」ことがわかりますが、内部バッファをクリアしていません)。 ReadByte を呼び出すたびにバッファー)。後続の ReadAsync への呼び出しごとにこれを行います - サーバーが切断される前に最後に送信したものでバッファーを補充します。コードの簡略版は次のとおりです。

    public async Task TestSocketConnectionAsync()
    {
        var socket = new StreamSocket();
        await socket.ConnectAsync(new HostName(Host), Port.ToString(),
            SocketProtectionLevel.PlainSocket);
        var dr = new DataReader(socket.InputStream);
        dr.InputStreamOptions = InputStreamOptions.Partial;

        this.cts = new CancellationTokenSource();
        this.listenerOperation = StartListeningAsync(dr, cts);
    }

    public async Task StartListeningAsync(DataReader dr, CancellationTokenSource cts)
    {
        var token = cts.Token;
        while (true)
        {
            token.ThrowIfCancellationRequested();
            var readOperation = dr.LoadAsync(1024);
            var result = await readOperation;
            if (result <= 0 || readOperation.Status != Windows.Foundation.AsyncStatus.Completed)
            {
                cts.Cancel(); // never gets called, status is always Completed, result always > 0
            }
            else
            {
                while (dr.UnconsumedBufferLength > 0)
                {
                    byte nextByte = dr.ReadByte();

                    // DriveStateMachine(nextByte);
                }
            }
        }
    }
4

1 に答える 1

9

つまり、サーバーはデータをクライアントにストリーミングし、メタタグを使用することもあり、いつでも切断できます。私が抱えている問題は、サーバーが切断されたことを検出する方法がわからないことです。

「正常な」ソケットクロージャは、長さ0の読み取りとして反対側で検出できます。つまり、通常のストリームの終わりのように機能します。

「吸収性のある」ソケットクロージャーはより注意が必要です。反対側が閉じたことを検出するためにデータを送信する必要があり、その書き込みが失敗すると、追加の読み取りまたは書き込みは失敗するはずです(例外を除く)。プロトコルでデータの送信が許可されていない場合は、タイムアウトの期限が切れた後、接続が不良であると想定して、接続を閉じる必要があります。:(

アプリケーションによっては、「中止」ソケットクロージャーが正常な場合があります。特に、非常にビジーなサーバーは、リソースをより迅速に再利用できるため( 4ステップのソケットシャットダウンハンドシェイクを回避できるため)、接続をクランプで閉じるように作成される場合があります。

StreamSocketクラス、その入力ストリームまたは出力ストリーム、あるいは接続ステータスと関係のあるDataReader/DataWriterクラスにはイベントやプロパティがないようです。

DataReader/ DataWriter「接続」には関係ありません。それらは本当にただBitConverter、今回だけより良く設計されています。

StreamSocket「接続された」プロパティがない理由Socket.Connectedは、ほとんど役に立たず、間違いなく誤解を招くためだと思います。


とにかくバイトを読んでいるだけなので、を使用StreamSocket.InputStream.ReadAsyncする代わりに直接使用してみます。DataReaderのバグを発見した可能性があります。期待どおりに機能する場合は、 MicrosoftConnectDataReaderについて報告する必要があります。この関連フォーラムの投稿も参照してください。InputStream.ReadAsync

于 2012-04-11T01:39:58.757 に答える