| 

.NET C# Java Javascript Exception

2
Manchmal passiert es, dass mein Aufruf zu Socket.Receive zu wenig Daten zurückliefert. Das sieht so aus:
byte[] buf = new byte[512];
int anzahl = socket.Receive(buf);
Debug.Assert(anzahl == 4); //crash
return BitConverter.ToInt32(buf, 0);

Meistens klappt es aber besonders wenn der TCP-Server unter Last steht, liefert socket.Receive weniger als 4 Bytes zurück. Woran kann das liegen?
News:
09.08.2009
dataguru 41 1 2
5 Antworten
3
TCP ist ein Stream-Protokoll. D.h. es gibt auf der TCP-Ebene keine Pakete (ausser 1 Byte). Paketgrenzen müssen auf der Protokollebene implementiert werden.
Receive() muss also in einer Schleife aufgrufen werden. Wenn Receive() 0 zurückgibt, dann heisst das, dass der Sender die Verbindung geschlossen hat.

Also etwa so (geschweifte Klammern durch eckige ersetzen wegen BBCode):

byte{} buf = new byte{512};
int empfangenebytes = 0;
int anzahl = 0;
do
{
empfangenebytes = socket.Receive(buf, anzahl, buf.Size(), SocketFlags.None);
anzahl += empfangenebytes;
}
while(anzahl<4 && empfangenebytes>0);

Debug.Assert(anzahl == 4); //crash
return BitConverter.ToInt32(buf, 0);


Da sollte nichts mehr crashen (ausser bei einem Netzwerkfehler).
07.09.2009
wulver75 61 1 1
2
TCP-Verbindungen sind zuverlässig - d.h. wenn nicht alle gesendeten Daten ankommen wird im schlimmsten Fall ein Fehler erzeugt. Wenn keine Fehler erzugt wird dann werden die Daten korrket gesendet.

Das Problem wird dann wohl beim Senden der Daten auftreten.
09.08.2009
gfoidl 9,4k 3 5
2
Ohne jetzt mehr vom Code zu sehen, und wenn ich mir das Problem so durchlese, könnte man auf die Vermutung kommen das beim Senden zb ein Flush fehlt

Herzliche Grüße
Lars
31.08.2009
Lars Schmitt 371 1 4
2
Afaik ist nicht sichergestellt, dass alle gesendeten Daten in einem Rutsch gelesen werden können. Ebenfalls kann es sein, dass der Client nicht alle Daten in einem Rutsch sendet!
Ich prüfe in solchen Fällen den Rückgabewert der lesenden Funktion und rufe diese ggf. erneut auf, um den Rest zu empfangen.
07.09.2009
Patrick-Oliver 81 1 1
1
Die schockierende Tatsache über TCP/IP ist, dass es per Spezifikation zwar zuverlässig ist, aber keine Datagrammgrenzen respektiert. D.h. wenn Du in drei send-Calls z.B. 300, 400 und 500 Bytes schickst bevor Du den Socket schließt, liegt es innerhalb der Spezifikation, dass recv diesen Datenstrom als vier Pakete zu 200, 250, 350 und 400 Bytes empfängt.

Dieses Verhalten ist in der Praxis aber so selten, dass viele Programme mit der Annahme, dass Paketgrenzen respektiert werden, arbeiten und es (meist) überleben.
07.09.2009
pjacobi 1,1k 2 7

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH