.NET-Frage zu asynchronen Socket-Operationen und Nachrichtenrahmen

9

Ich habe überall nach Beispielen gesucht, wie man mit TCP-Nachrichtenrahmen umgehen kann. Ich sehe viele Beispiele, in denen NetworkStreams an ein StreamReader- oder StreamWriter-Objekt übergeben werden und dann ReadLine- oder WriteLine-Methoden für '\ n' getrennte Nachrichten verwenden. Mein Anwendungsprotokoll enthält Nachrichten, die auf '\ n' enden, also scheint der NetworkStream der richtige Weg zu sein. Ich kann jedoch keine spezifischen Beispiele finden, wie all dies in Kombination mit asynchronen Sockeln gehandhabt werden kann. Wie kann ich, wenn ReceiveCallback () unten aufgerufen wird, die NetworkStream- und StreamReader-Klassen implementieren, um mit dem Framing von Nachrichten umzugehen? Entsprechend dem, was ich gelesen habe, kann ich einen Teil einer Nachricht in einem Empfang erhalten und den Rest der Nachricht (einschließlich des '\ n') beim nächsten Empfang. Bedeutet das, dass ich das Ende einer Nachricht und einen Teil der nächsten Nachricht erhalten könnte? Sicherlich muss es einen einfacheren Weg geben, damit umzugehen.

Ich habe den folgenden Code:

%Vor%     
Andrew 19.05.2011, 02:14
quelle

3 Antworten

1

Grundsätzlich erstellen Sie einen Puffer, und jedes Mal, wenn Sie Daten empfangen, fügen Sie diese Daten dem Puffer hinzu und bestimmen, ob Sie bereits eine oder mehrere vollständige Nachrichten erhalten haben.

Zwischen ReceiveCallback und StartRead erhalten Sie keine asynchronen Nachrichten (eingehende Daten werden automatisch auf der Socket-Ebene gepuffert). Dies ist der ideale Ort, um nach vollständigen Nachrichten zu suchen und diese aus dem Puffer zu entfernen.

Alle Variationen sind möglich, einschließlich des Empfangs des Endes der Nachricht 1 plus Nachricht 2 plus dem Beginn der Nachricht 3, alles in einem Stück.

Ich empfehle UTF8-Decodierung des Chunks nicht, da ein UTF8-Zeichen aus zwei Bytes bestehen kann, und wenn sie zwischen Chunks aufgeteilt werden, könnten Ihre Daten beschädigt sein. Sie könnten in diesem Fall ein Byte [] - Puffer ( MemoryStream ?) Behalten und Nachrichten auf das 0x0A-Byte aufteilen.

    
C.Evenhuis 19.05.2011, 12:46
quelle
3

Das Vorfixieren der Chunks mit einer Länge ist besser als die Verwendung eines Trennzeichens. Sie müssen sich nicht mit irgendeiner Art von Entweichen befassen, um Daten mit einer neuen Zeile auf diese Weise zu senden.

Diese Antwort ist für Sie möglicherweise nicht relevant, da sie Funktionen aus dem AsyncCTP verwendet, die wird nur in der nächsten Version von .net sein. Es macht jedoch die Dinge viel prägnanter. Im Wesentlichen schreiben Sie genau den Code, den Sie für den synchronen Fall verwenden würden, aber fügen Sie 'wait'-Anweisungen ein, wenn asynchrone Aufrufe vorliegen.

%Vor%     
Craig Gidney 19.05.2011 15:04
quelle
0

OK, hier ist, was ich getan habe. Ich habe einen Reader-Thread erstellt, der basierend auf dem Netzwerk-Stream einen NetworkStream und einen StreamReader erstellt. Dann benutze ich StreamReader.ReadLine, um die Zeilen so einzulesen. Es ist ein synchroner Aufruf, aber es ist in einem eigenen Thread. Es scheint viel besser zu funktionieren. Ich musste dies implementieren, da das unser Protokoll für die Anwendung ist (newline-limited messages). Ich weiß, dass andere Leute sich wie die Hölle um die Antwort kümmern werden, so wie ich es getan habe, hier ist der relevante Lesecode in meiner Clientklasse:

%Vor%     
Andrew 19.05.2011 22:47
quelle

Tags und Links