Moin,
ich hab n Problem mit einer Socketbasierten TCP/IP Client-Server Anwendung. Und zwar sende ich zum Performancetest etwa 10000 Anfragen a 8 byte in einer for-Schleife und einem seperaten Thread. Nun habe ich aber das Problem eines zu potenten Servers, dass heißt, dass teilweise mehrere Antworten auf einmal in ein und demselben Result zurückkommen und teilweise auch abgeschnitten werden, wenn der Puffer voll ist.
Gibt es eine Möglichkeit, dass die Anfragen so zurück kommen, wie ich sie gesendet habe? Das Senden langsamer zu machen ist dabei aber keine Option.
Unser Code sieht so aus:
private void ReciveData(IAsyncResult result)
{
if (server.Running)
{
if (!Avilable)
Avilable = true;
int offset = 0;
try
{
offset = cTCPConnection.Client.EndReceive(result);
}
catch(SocketException e)
{
this.Avilable = false;
return;
}
catch (ObjectDisposedException e)
{
this.Avilable = false;
return;
}
if (offset == 0)
{
Avilable = false;
return;
}
if (!Subscribed)
{
subscribed = true;
server.CastConnectionEvent(this);
}
List<byte> bytes = new List<byte>();
bytes.AddRange(buffer);
bytes.RemoveRange(offset, bytes.Count - offset);
server.CastTransmissionEvent(bytes.ToArray(), this);
try
{
cTCPConnection.Client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReciveData, null);
}
catch(SocketException e)
{
this.Avilable = false;
}
catch (ObjectDisposedException e)
{
this.Avilable = false;
}
}
}
Kann ich da eventuell was über das Socketflagg machen?
Hallo,
die Daten werdene halt einfach in den Stream geschrieben und auf der Gegenseite wird der Stream gelesen. Die einzelnen Nachrichten musst Du auf der Gegenseite selbst auseinandernehmen, denn dort wird durch einen Aufruf einer der Read-Methoden alles gelesen, was bereits verfügbar ist - bis maximal zur Puffergrösse.
Wenn Nachrichten "abgeschnitten" werden, musst Du den Rest halt hinterher noch lesen (in einer Schleife, bis nix mehr verfügbar ist).
Gruß, MarsStein
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
ja aber gibts da nichts internes, dass das verhinert?
Ich mein die Packete werden ja auf layerebene auch nummeriert. Kann ich dem result nicht sagen, dass es nur warten soll bis ein sendesatz komplett ist (also bis packete 1, 2 und 3/3 da sind)?
Hallo,
ja aber gibts da nichts internes, dass das verhinert? Nein.
die Packete werden ja auf layerebene auch nummeriert. Richtig. Aber es ist keinesfalls sichergestellt, das ein Packet auf TCP-Ebene Deinen einzelnen Senedeaufrufen entspricht. Es ist durchaus möglich (und sehr wahrscheinlich), dass Daten aus aufeinanderfolgenden Sendeaufrufen in einem TCP-Packet versendet werden.
Das einzige worauf Du Dich verlassen kannst, ist, dass die Reihenfolge der Daten richtig ist, sofern Du TCP und nicht UDP benutzt.
EDIT:
Kann ich dem result nicht sagen, dass es nur warten soll bis ein sendesatz komplett ist (also bis packete 1, 2 und 3/3 da sind)? Wenn Du die Größe der einzelnen Pakete kennst, kannst Du das ggf. mit einer entsprechenden Puffergröße beim Lesen steuern, allerdings nur bei einem stabilen, schnellen Netzwerk. Und auch da würde ich an Deiner Stelle auf jeden Fall noch auswerten, wieviele Bytes tatsächlich emfangen wurden!
Gruß, MarsStein
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
sofern Du TCP und nicht UDP
Ne, Ne, ist schon TCP.
Wenn Du die Größe der einzelnen Pakete kennst, kannst Du das ggf. mit einer entsprechenden Puffergröße beim Lesen steuern, allerdings nur bei einem stabilen, schnellen Netzwerk.
Du meinst also, wenn ich Packete mit 8byte versende, sollte ich einen Puffer von 8Byte größe verwenden, um zu gewährleisten, dass die Daten alle einzeln ankommen?
Ist denn dabei auch gewährleistet, dass auch wirklich die gesendeten 8byte im Puffer sind und nicht etwa 2 teile von 2 verschiedenen sendungen?
Und auch da würde ich an Deiner Stelle auf jeden Fall noch auswerten, wieviele Bytes tatsächlich emfangen wurden!
Wie meinst du denn das? Ich erhalte ja über die empfangsmethode ein Array, welches immer genauso groß ist, wie die bei cTCPConnection.Client.EndReceive(result) erhaltenen Elemente in meinem Puffer
Hallo,
Du meinst also, wenn ich Packete mit 8byte versende, sollte ich einen Puffer von 8Byte größe verwenden, um zu gewährleisten, dass die Daten alle einzeln ankommen? Ja, genau so meinte ich das.
Ist denn dabei auch gewährleistet, dass auch wirklich die gesendeten 8byte im Puffer sind und nicht etwa 2 teile von 2 verschiedenen sendungen? Leider nicht. Es sollte zwar der Regelfall sein, aber ganz sicher kannst Du im Netzwerk leider nie sein. Wenn Du einen Puffer von 8 Bytes benutzt, passt da zwar genau ein Paket rein - deshalb kannst Du mit einem Aufruf auch nicht mehr erhalten, aber es könnte schon sein, dass es weniger ist und der Rest noch hinterherkommt.
Um das zu lösen, kannst Du im Fall von weniger enthaltenen Bytes die bereits erhaltenen Bytes (bei mehreren Aufrufen deren Summe) beim nächsten Lesen als offset
angeben und als Länge liest Du nur noch die zu erwartende Anzahl, etwa so, wobei myOffset
der Anzahl der bereits in den Puffer gelesenen Bytes enspricht:
Client.BeginReceive(buffer, myOffset, buffer.Length-myOffset, SocketFlags.None, ReciveData, null);
Gruß, MarsStein
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
OK, habs getestet und mit dem reduzierten Puffer hats geklappt.
Mein Performancecounter hat auch keine Packete verschludert oder vermatscht.
(übers Netzwerk an meinen Server in Düsseldorf und wieder zurück)