2017-04-23 9 views
0

Ich habe eine TCP-Server-Anwendung programmiert, wo ich eingehende Verbindungen an einem dedizierten Port abhören kann. Damit kann ich ein "verbundenes" Ereignis bekommen und dann Daten empfangen (nur einmal).UWP TCP Daten kontinuierlich empfangen

Wie kann ich kontinuierlich Daten vom Port empfangen (und vielleicht auch feststellen, ob der Client noch angeschlossen ist)?

Ich habe ein NodeMCU (Arduino-basiertes) System angeschlossen, das jede Temperatur über die TCP-Verbindung sendet.

Starten und Stoppen des Servers über einen Kippschalter in der Benutzeroberfläche:

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; 
} 

Ereignis, das eine neue Verbindung behandelt und Empfangen von Daten:

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); 
} 

Dieser Code funktioniert perfekt auf die Daten einmal erhalten Die Verbindung ist hergestellt.

Ich denke an eine Lösung, um ein Ereignis zu erhalten, sobald neue Daten im Eingabepuffer sind und dann die Daten verarbeiten.

Antwort

1

Ich denke an eine Lösung, um ein Ereignis zu erhalten, sobald neue Daten im Eingabepuffer sind und dann die Daten verarbeiten.

Es gibt kein solches Ereignis in der UWP-API, das bei jedem Empfang eines neuen Datums ausgelöst werden kann. Normalerweise verwenden wir eine While-Schleife, um Daten kontinuierlich zu empfangen. Zum Beispiel können Sie eine while-Schleife in Ihrer LocalSocketConnectionReceived Methode, wie die folgenden hinzu:

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

Die while-Schleife arbeitet hier, weil Data​Reader.LoadAsync(UInt32) eine asynchrone Methode ist. Es wird dort warten, wenn kein Datum empfangen wird.

Weitere Informationen finden Sie in der StreamSocket sample auf GitHub, vor allem die OnConnection Methode in Szenario 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

ich arround jetzt mit diesem Thema beschäftigt und Empfang der Nachrichten arbeitet mit dieser Methode gut. Wenn ich die Verbindung/den Server schließe, bekomme ich immer eine Ausnahme "System.ObjectDisposedException" in der Zeile "awarn reader.LoadAsync ((uint) payloadSize.Length);' da der Input Socket geschlossen wurde. Wie kann ich die while-Schleife davon abhalten, den Port anzuhören? – Christoph

Verwandte Themen