2017-04-23 88 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