C # Warum zwingt "Flush" die Bytes nicht in den Netzwerkstrom?

8

Ich habe ein Projekt, bei dem ich versuche, ein serialisiertes Objekt an den Server zu senden, und dann auf die Meldung "OK" oder "FEHLER" zu warten, um zurück zu kommen.

Ich habe anscheinend ein ähnliches Problem mit dem Poster von: TcpClient senden / schließen Problem

Das Problem ist, dass ich das ursprüngliche Objekt scheinbar nur senden kann, indem ich die Verbindung schließe, aber dann (natürlich) kann ich nicht warten, ob das Objekt vom Server erfolgreich verarbeitet wurde.

%Vor%

UPDATE: Als Antwort auf einen Kommentator glaube ich nicht, dass der Client einen Fehler machen kann. Es wartet einfach auf das Objekt, und das Objekt kommt nie, bis ich den Sockel schließe ... aber wenn ich falsch liege, werde ich GLAUßLICH Krähe öffentlich essen. =) Hier ist der Kunde:

%Vor%

Ja .... so einfach ist das.

    
Jerry 15.02.2011, 18:51
quelle

4 Antworten

3

Die kurze Version ist scheinbar, wenn XmlSerializer (oder irgendein anderer großer Blob) verwendet wird, um Daten in einen NetworkStream zu schieben, wird es die Zeile einfach auf unbestimmte Zeit warten lassen, bis weitere Informationen geschrieben werden. Es spült nur die Verbindung, sobald Sie es schließen. Dies erzeugt eine Situation, in der diese Methode zum Senden, aber nicht zum Empfangen geeignet ist. Oder umgekehrt. Es wird eine Einwegkommunikation und für die fortgesetzte Hin-und-Her-Kommunikation über dieselbe Verbindung nutzlos.

Es ist irgendwie beschissen, dass ich an etwas arbeiten musste, das an der Oberfläche so elegant wirkte, aber zu meinen alten C-Tagen zurückkehrte, habe ich zuerst ein "Anzahl von Bytes" -Paket gesendet, dann das eigentliche Paket . Dies ermöglicht es mir, am anderen Ende die genaue Anzahl der Bytes zu lesen, so dass ich nie in einem Blockierungsmuster gefangen bin.

Um mein Leben zu vereinfachen, habe ich eine Klasse erstellt, die statische Methoden zum Senden und Empfangen enthält. Diese Klasse kann jede XML-serialisierbare Klasse über das Netzwerk senden, also tut sie, was ich tun muss.

Wenn jemand eine elegantere Lösung hat, wäre ich offen dafür, es zu hören.

%Vor%

Um diese Klasse zu verwenden, muss ich einfach PacketTransit.SendPacket(myTcpClient, SomePacket) aufrufen, um ein beliebiges XML-serialisierbares Objekt zu senden. Ich kann dann PacketTransit.GetResponsePacket oder PacketTransit.GetRequestPacket verwenden, um es am anderen Ende zu erhalten.

Für mich funktioniert das sehr gut, aber es war viel mehr Training als ursprünglich erwartet.

    
Jerry 17.02.2011, 16:28
quelle
3

Oh oh, Sie können Nagles Algorithmus dafür verantwortlich machen. Es hat jedoch nichts mit C # zu tun, es ist ein Standardverhalten für den TCP / IP-Stack. Aktivieren Sie die Socketoption NoDelay mit SetSocketOption -Methode. Aber Vorsicht: Wenn Nagles Algorithmus deaktiviert wird, wird der Durchsatz herabgesetzt.

Ich bin mir auch nicht sicher über den Stream, den Sie oben auf dem Socket verwenden, da ich überhaupt kein C # -Entwickler bin, aber versuchen Sie, seine Instanz fallen zu lassen, damit sie sicher schreibt: -)

    
user405725 15.02.2011 18:57
quelle
0

Sie sollten einen StreamWriter / Reader verwenden, der mit Ihrem Netzwerk-Stream verbunden ist, .Flush tut nichts auf einem NetworkStream, siehe hier:

Ссылка

    
Davide Piras 15.02.2011 18:57
quelle
0

Ich glaube, das wirkliche Problem hier könnte sein, dass der XmlDeserializer möglicherweise erst zurückkehrt, wenn er EOS aus dem Stream gelesen hat. Möglicherweise müssen Sie den sendenden Stream für die Ausgabe herunterfahren, um dies zu erzwingen.

    
EJP 14.03.2013 03:04
quelle