2012-04-10 170 views
5

我有一个应用程序,我正在为Windows 8/WinRT编写,它使用StreamSocket API与服务器建立流连接。也就是说,服务器将数据流式传输到客户端,有时使用元标记,并且可以随时断开连接。处理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

也就是说,服务器流数据到客户端,有时meta标签,并且可以随时断开。我遇到的问题是,我不知道如何检测服务器何时断开连接。

“优美”的套接字关闭可以被另一端检测为0长度读取。也就是说,它只是像一个常规的流结束。

“失败”套接字关闭更加棘手。您检测到对方已关闭,并且一旦写入失败,则任何其他读取或写入都将失败(有例外)。如果您的协议不允许您发送数据,那么在超时到期并且关闭后,您必须假定连接不正确。 :(

根据应用的“流产”套接字关闭可能是正常 - 尤其是非常繁忙的服务器可能会被写入夹住关闭他们的连接,因为它可以让他们更快地回收资源(避免 - 工序套接字关闭握手)。

似乎没有要上StreamSocket类的任何事件或属性,无论是它的输入或输出流,或者有什么关系连接的DataReader/DataWriter类状态

DataReader/DataWriter不关心“连接”。它们实际上只是BitConverter,这次只是设计得更好。

我猜想StreamSocket没有“连接”属性的原因是因为Socket.Connected is nearly useless and definitely misleading


我会尝试使用StreamSocket.InputStream.ReadAsync,而不是直接使用DataReader,因为你只是读取字节反正。这听起来像你可能已经发现了DataReader中的一个错误,如果InputStream.ReadAsync按预期工作,你应该报告Microsoft Connect。另见this related forum post

+1

这是很好的信息要知道。谢谢。看起来DataReader.ReadAsync问题是一个错误,而且似乎微软内部的相应团队已经意识到了这一点,所以希望能够得到解决。与此同时,我尝试了在我自己的IBuffer上调用InputStream.ReadAsync(来自WindowsRuntimeBuffer.Create)的建议,它不仅可以工作,而且它的延迟时间似乎减少了很多。 – 2012-04-11 14:22:02

+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 2014-12-18 01:07:47

相关问题