2017-04-23 113 views
0

我編寫了一個TCP服務器應用程序,我可以在專用端口上偵聽傳入連接。有了這個,我可以得到一個「連接」事件,然後接收數據(只有一次)。UWP TCP連續接收數據

如何從端口連續接收數據(也可能檢測客戶端是否仍連接)?

我已經連接了一個NodeMCU(基於Arduino的)系統,它使用TCP連接每秒發送一些溫度數據。

啓動,並通過在UI切換開關停止服務器:

public async Task<bool> StartListeningAsync() 
{ 
    if (TCPSocket == null) 
    { 
     TCPSocket = new StreamSocketListener(); 
     TCPSocket.ConnectionReceived += LocalSocketConnectionReceived; 
     await TCPSocket.BindServiceNameAsync(CommunicationPort); 
     return true; 
    } 
    return false; 
} 

public async Task<bool> StopListening() 
{ 
    if (connectedSocket != null) 
    { 
     connectedSocket.Dispose(); 
     connectedSocket = null; 
    } 

    if (TCPSocket != null) 
    { 
     await TCPSocket.CancelIOAsync(); 
     TCPSocket.ConnectionReceived -= LocalSocketConnectionReceived; 
     TCPSocket.Dispose(); 
     TCPSocket = null; 
     return true; 
    } 

    return false; 
} 

事件處理一個新的連接和接收數據:

private async void LocalSocketConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) 
{ 
    if (connectedSocket != null) 
    { 
     connectedSocket.Dispose(); 
     connectedSocket = null; 
    } 
    connectedSocket = args.Socket; 


    await textBox_send.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,() => 
    { 
     textBox_send.IsEnabled = true; 
     txtConnected.Text = "Client Connected"; 
    }); 

    using (var reader = new DataReader(args.Socket.InputStream)) 
    { 
     await readTCPDataAsync(reader); 
    } 

} 

private async Task readTCPDataAsync(DataReader reader) 
{    
    reader.InputStreamOptions = InputStreamOptions.None; 

    // Read the length of the payload that will be received. 
    byte[] payloadSize = new byte[(uint)BitConverter.GetBytes(0).Length]; 
    await reader.LoadAsync((uint)payloadSize.Length); 
    reader.ReadBytes(payloadSize); 


    // Read the payload. 
    int size = BitConverter.ToInt32(payloadSize, 0); 
    //size = 2; 
    byte[] payload = new byte[size]; 
    await reader.LoadAsync((uint)size); 
    reader.ReadBytes(payload); 

    string data = Encoding.ASCII.GetString(payload); 
} 

此代碼工作完全一旦接收數據連接建立。

我正在考慮解決方案來獲取一個事件,一旦新的數據在輸入緩衝區,然後處理數據。

回答

1

我在想一個解決方案,一旦新數據在輸入緩衝區上,然後處理數據,就會得到一個事件。

在每次收到新日期時都可以觸發的UWP API中沒有這樣的事件。我們通常在這裏使用while循環來連續接收數據。例如,你可以在你LocalSocketConnectionReceived方法添加一個while循環類似如下:

using (var reader = new DataReader(args.Socket.InputStream)) 
{ 
    while (true) 
    { 
     await readTCPDataAsync(reader); 
    } 
} 

while循環在這裏工作,因爲Data​Reader.LoadAsync(UInt32)是一個異步方法。如果沒有收到日期,它將在那裏等待。

欲瞭解更多信息,請參閱StreamSocket sample GitHub上,尤其是OnConnection方法場景1

/// <summary> 
/// Invoked once a connection is accepted by StreamSocketListener. 
/// </summary> 
/// <param name="sender">The listener that accepted the connection.</param> 
/// <param name="args">Parameters associated with the accepted connection.</param> 
private async void OnConnection(
    StreamSocketListener sender, 
    StreamSocketListenerConnectionReceivedEventArgs args) 
{ 
    DataReader reader = new DataReader(args.Socket.InputStream); 
    try 
    { 
     while (true) 
     { 
      // Read first 4 bytes (length of the subsequent string). 
      uint sizeFieldCount = await reader.LoadAsync(sizeof(uint)); 
      if (sizeFieldCount != sizeof(uint)) 
      { 
       // The underlying socket was closed before we were able to read the whole data. 
       return; 
      } 

      // Read the string. 
      uint stringLength = reader.ReadUInt32(); 
      uint actualStringLength = await reader.LoadAsync(stringLength); 
      if (stringLength != actualStringLength) 
      { 
       // The underlying socket was closed before we were able to read the whole data. 
       return; 
      } 

      // Display the string on the screen. The event is invoked on a non-UI thread, so we need to marshal 
      // the text back to the UI thread. 
      NotifyUserFromAsyncThread(
       String.Format("Received data: \"{0}\"", reader.ReadString(actualStringLength)), 
       NotifyType.StatusMessage); 
     } 
    } 
    catch (Exception exception) 
    { 
     // If this is an unknown status it means that the error is fatal and retry will likely fail. 
     if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) 
     { 
      throw; 
     } 

     NotifyUserFromAsyncThread(
      "Read stream failed with error: " + exception.Message, 
      NotifyType.ErrorMessage); 
    } 
} 
+0

我與這個主題角落找尋工作現在用這種方法接收郵件工作正常。 當我關閉連接/服務器時,我總是會在await reader.LoadAsync((uint)payloadSize.Length)行中得到異常「System.ObjectDisposedException」;'因爲輸入套接字已關閉。我怎樣才能阻止while循環聽從端口? – Christoph