2012-04-10 28 views
5

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

私が抱えている問題は、サーバーが切断されたときの検出方法がわからないことです。 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); 
       } 
      } 
     } 
    } 

答えて

9

時々メタタグを持つクライアントに、サーバーのストリームデータを、言うことで、いつでも切り離すことができます。ここでは、コードの簡易版です。私が抱えている問題は、サーバーが切断されたときをどのように検出するのか分かりません。

"グレースフル"ソケットクロージャは、0側の読み取りとして相手側で検出できます。つまり、通常のストリーム終わりのように機能します。

"不完全な"ソケットクロージャは、よりトリッキーです。あなたはhave to send dataで、反対側が閉じていることを検出し、書き込みが失敗すると、追加の読み取りまたは書き込みが失敗する(例外を伴います)必要があります。あなたのプロトコルでデータを送信することができない場合は、タイムアウトが切れた後に接続が悪いとみなして閉じてください。 :(

は、アプリケーションに応じて、「失敗に終わった」ソケットの閉鎖とすることができる 通常 - 特に、非常に忙しいのサーバーは、それは彼らが回避(より迅速にリソースを再利用することができますので、その接続をシャットダウンクランプに書き込むことができます)-stepソケットシャットダウン握手。

ありStreamSocketクラス上の任意のイベントやプロパティのように見える、のいずれかの入力または出力ストリーム、または接続を行うには何も持っているのDataReader/DataWriterクラスではありませんステータス。

DataReader/DataWriterは実際にはBitConverterですが、今度はもっと良く設計されています。

には接続されたプロパティがないと推測します。これはSocket.Connected is nearly useless and definitely misleadingです。


私はあなただけでとにかくバイトを読んでいることから、StreamSocket.InputStream.ReadAsyncを使用して、直接の代わりDataReaderを使用しようとするだろう。 DataReaderのバグを発見した可能性があります。に報告する必要があります。InputStream.ReadAsyncが期待通りに機能する場合は、それを報告してください。また、this related forum postを参照してください。

+1

これは知っておくと良い情報です。ありがとうございました。 DataReader.ReadAsyncの問題はバグであり、マイクロソフト内の適切なチームがそれを認識しているように見えるので、うまくいけばそれが解決されます。その間、私は自分のIBuffer(WindowsRuntimeBuffer.Createから)でInputStream.ReadAsyncを呼び出すというあなたの提案を試みただけでなく、それが顕著な量で待ち時間を短縮したように見えます。 –

+0

この古い投稿が見つかりました。 @JeremyBellは 'InputStream.ReadAsync'についてあなたが開いたユーザーの声のバグは何ですか?それは今解決されていますか?私は入力ストリームに奇妙な振る舞いをしていて、そこにはいけないサーバーからの応答を積み重ねているようだ。新しいデータをサーバーに送信する前に、ソケットからすべてのデータを読み取る必要があります。 http://stackoverflow.com/questions/27533703/how-to-read-all-the-available-data-from-a-winrt-streamsocket-and-empty-the-input?noredirect=1#comment43496033_27533703を参照してください。 – philk

関連する問題