2012-04-10 258 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

相關問題