Laden...

UDP Kommunikation Performance Problem

Erstellt von akoh vor 11 Jahren Letzter Beitrag vor 11 Jahren 5.657 Views
A
akoh Themenstarter:in
8 Beiträge seit 2012
vor 11 Jahren
UDP Kommunikation Performance Problem

Hallo Zusammen,

ich bin sehr neu im Thema Kommunikation und weiß nicht mehr weiter.

Problemstellung:

Client Linux c++ udpsocket --> eine while loop schickt ca. 7 Udp Packete an Server.
Gesamtgröße der 7 Packete ca 0,3MB (1 Bild).

Server WIN7 GUI(WINForms) .net sockets-->
ein thread der nichts anderes macht als "receivefrom(...)"
D.h. dieser Thread schreibt ununterbrochen in ein Buffer.
Um zeit zu sparen werden viele Buffer im voraus erstellt und dann nur noch rotierend benutzt.

Insgesamt:
1xMainThread
2x andere Threads
1 x UDP_recv-Thread

Das Problem ist, dass die Clientseite so schnell schickt, dass der Reveiver Thread, obwohl er nur die receiveMethode ausführt nicht hinter her kommt und dadurch packete verloeren gehen.

Ich weiß das es an der Performance dieses Threads liegt, da ich schon auf der Clientseite mit einem sleep(...), dass ganze etwas gedrosselt habe und siehe da, alles kommt an wie es ankommen sollte.

Nun weiß ich nicht wie ich das machen soll, um das empfangen zu beschleunigen. Schließlich kann ich ja die Thread-Zeitscheibe(time slice) nur durch die Priorität ändern(probiert -->kein Erfolg).

Gibt es vielleicht eine Möglichkeit den UDP-Thread auf ein Kern legen und die restlichen Threads auf den anderen. Habe aber dafür noch keine praktische Lösung gefunden.

Und das ich die Drossel auf der Clientseite lasse ist ja wohl auch keine Lösung mit der ich mich auch nur ansatzweise zufrieden geben kann.

Asynchrones Empfangen ist so wie ich das verstehe auch keine Lösung, oder verstehe ich das falsch und es ist die Lösung?

Wie machen es die Könner 😃 bei ihren Video-oder Audiostreamings?

Nachträglicher Eintrag:
mit lock(was ja ein kritischer Bereich ist) habe ich auch kein Erfolg gehabt.

[CODE]lock(this)
{
    receivefrom(...);
    receivefrom(...);
    receivefrom(...); // usw also so oft hintereinander bis ein volles bild empfangen werden sollte
}[/CODE]

Das bedeutet, dass das ein allgemeines UDP "Synchronisationproblem" besteht...
oder sehe ich das falsch?

W
872 Beiträge seit 2005
vor 11 Jahren

Du solltest Dich m.E. mit RTP oder einem anderen Streaming-Protokoll beschäftigen, dass auf UDP basiert, aber das Problem beseitigt, wenn (aus welchem Grund auch immer) Pakete verloren gehen. Eine Beschleunigung des Servers wird nicht das Problem zufriedenstellend lösen.
Der Artikel How to use the managed RTP API Classes in .NET sollte Dir dazu Anregungen geben.
Ansonsten solltest Du mal Deinen Code zeigen. An sich solltest Du in der schnellsten Form nur einmal ein Byte-Array anlegen und dann mit Offset an die richtige Stelle direkt in dein Byte-Array schreiben. Da ist dann der Unterschied zwischen nativem und C# Code sehr klein.

A
akoh Themenstarter:in
8 Beiträge seit 2012
vor 11 Jahren

Danke erstmal für RTP... kannte ich bisher noch nicht, muss ich mir mal genauer anschauen!

Was macht das für ein Unterschied ob ich ein großes ByteArray habe oder mehrere kleinere? Im Endeffekt wird doch trotzdem nur eine Referenz übergeben!?

mein ReceiveThread:


for(;;)
{
    receivefrom(buffer, localEP);
    wt.set();           //wt = AutoEventHandler
}

mehr macht dieser Thread nicht --> wie gesagt es liegt entweder daran das die methode zu langsam ist (warum auch immer), oder daran dass die Zeitscheiben eben nicht "richtig" verteilt werden.

W
872 Beiträge seit 2005
vor 11 Jahren

*Jedes Array hat einen Overhead in C#, da die Arrays typsicher sind und die Länge geprüft wird. *Mehrere Arrays fuehren zur Defragmentierung vom Hauptspeicher. Das kann die Garbage Collection verlangsamen.

5.742 Beiträge seit 2007
vor 11 Jahren

Hallo akoh,

warum nimmst du überhaupt UDP, wenn keine Pakete verloren gehen dürfen?!?
Hierzu Wikipedia:

IP löscht Pakete etwa bei Übertragungsfehlern oder bei Überlast. Datagramme können daher fehlen. UDP bietet hierfür keine Erkennungs- oder Korrekturmechanismen, wie etwa TCP. Im Falle von mehreren möglichen Routen zum Ziel kann IP bei Bedarf neue Wege wählen. Dadurch ist es in seltenen Fällen möglich, dass später gesendete Daten früher gesendete überholen. Außerdem kann ein einmal abgesendetes Datenpaket mehrmals beim Empfänger eintreffen.

Willst du das wirklich? Was spricht gegen TCP?

Was macht denn deine receivefrom-Methode?
Evtl. blockiert die ja.

Deine Paketgröße von knapp 43kB scheint mir auch recht groß gewählt; soweit ich weiß, wird das Paket dann gesplittet übertragen (kA, was genau passiert, wenn dann eines der Teilpakete verloren geht).

oder daran dass die Zeitscheiben eben nicht "richtig" verteilt werden.

Aha - mal wieder einen Bug in Windows entdeckt...

W
872 Beiträge seit 2005
vor 11 Jahren

Hi Winsharp,
TCP ist nicht so gut geeignet, da TCP nicht nur Paketverluste verhindert, sondern sogar die Reihenfolge der TCP Pakete garantiert. Wenn Du nun ein Paket verlierst, dann wird nicht nur das fehlende Paket, sondern auch alle folgenden Pakete wieder gesendet (TCP Requeue). Bei einem Requeue durch einen ueberlasteten Server kommst Du so schnell in eine sehr missliche Situation, in der Dir nur ein Restart hilft, damit die TCP Queues komplett leer geraeumt werden.
Streaming Protokolle wie RTP basieren auf UDP, verhindern aber den Paketverlust, ohne, dass alle Pakete wieder geschickt werden, sondern nur das verlorene Paket.
Deine Anmerkung mit denPaket-Groessen halte ich fuer richtig/wichtig, denn das wird wahrscheinlich der Grund fuer den Paketverlust sein.

A
akoh Themenstarter:in
8 Beiträge seit 2012
vor 11 Jahren

Der Unterschied zwischen UDP und TCP ist mir sehr wohl bewusst und UDP wurde auch von mir gezielt gewählt (siehe Beitrag drüber):
Außerdem läuft die Verbidung über WLAN--> WLAN und TCP und hoher Datenstrom ist nicht wirklich eine gute Idee --> das einzige was man ausprobieren könnte, wäre die Packetanzahl zu erhöhen um somit Packetgröße zu veringern --> Dadurch erhoffe ich mir geringer Verzugszeiten bei fehlerhaften Versendung

So noch zur Packetgröße: wie meinst du das, dass das Packet gesplitet übertragen wird?
Ich habe die Packetgrößen mal auf 10k runter geschraubt-->ist tatsächlich besser geworden, aber immer noch nicht zufriedenstellen.(habe noch immer kein volles Bild)

W
872 Beiträge seit 2005
vor 11 Jahren

So wird die Frage nach der Paketgroesse bei Stackoverflow beantwortet.
Ich wuerde mal 512 probieren - nie vergessen, dass ein viele udp messages wie eine DoS-Attacke wirken - bin da ein gebranntes Kind...

16.830 Beiträge seit 2008
vor 11 Jahren

Außerdem läuft die Verbidung über WLAN--> WLAN und TCP und hoher Datenstrom ist nicht wirklich eine gute Idee

Ob das als gute Idee einzustufen ist oder nicht, das bestimmen vor allem die Nachteile.

Bei UDP weist Du nie, ob alle Pakete wirklich ankommen.
Das ist bei einem Video egal, wenn da mal nen Pixel fehlt. Aber wenn Du alle Pakete brauchst, dann ist UDP eben nicht die richtige Wahl. Klassisches K.O.-Kriterium.
Ob RTP hier die Lösung des Üblen ist lasse ich mal dahin gestellt.

Zum Thema TCP in Funknetzen: MIT researchers use algebraic equation that improves WiFi and LTE data streams: boosts speed, reduces network congestion

156 Beiträge seit 2010
vor 11 Jahren

Moin, mein Senft dazu,

Das Problem ist, dass die Clientseite so schnell schickt, dass der Reveiver Thread, obwohl er nur die receiveMethode ausführt nicht hinter her kommt und dadurch packete verloeren gehen.

Ich weiß das es an der Performance dieses Threads liegt, da ich schon auf der Clientseite mit einem sleep(...), dass ganze etwas gedrosselt habe und siehe da, alles kommt an wie es ankommen sollte.

Wer sagt das der Server zu langsam ist? Evt. könnte es auch an Deinem lokalen Netzwerk liegen. UDP Pakete werden verworfen weil etwas bei der Übertragung nicht stimmt bzw. etwas schief gelaufen ist. Das kann bei einem ausgelastetem Netzwerk auch eine simple Kollision auf der Leitung sein. Wenn Du die sende-Frequenz drosselst, dann reduzierst Du automatisch die Kollisionen. Kann auch sein das Dein WLAN-Router selber nicht die Datenmenge verarbeiten kann. (1)

Gibt es vielleicht eine Möglichkeit den UDP-Thread auf ein Kern legen und die restlichen Threads auf den anderen. Habe aber dafür noch keine praktische Lösung gefunden.

Mit Thread-Prioritäten und Kernen rumzuspielen macht nur an zwei Stellen Sinn. Dein Problem gehört weder zum Thema Gameserver oder Bild/Daten-Verarbeitung.

Wie machen es die Könner 😃 bei ihren Video-oder Audiostreamings?

Lösungen wurden schon genannt
-> Leben das Pakete verloren gehen
-> RTP Streaming verwenden und Bilder Zeitversetzt sehen
-> TCP verwenden (ist aber vom Hauptproblem abhängig)

Da du nicht genau schreibst was Du am Client mit den Bildern genau machen willst, gibt es auch keine besseren Lösungsvorschläge.

hand, mogel

(1) nur weil ein Protokoll behauptet das man damit 300MBit/Sekunde übertragen kann, muss das noch lange nicht vom Gerät unterstützt werden. Aktuelles Beispiel: RS485 kann lt. Spezifikation 12MBit - mein Gerät schafft aber nur 115kBit. Mehr ist technisch nicht machbar. Ergo -> auch ein WLAN-Router schafft nicht immer alles.

A
akoh Themenstarter:in
8 Beiträge seit 2012
vor 11 Jahren

Danke für die Anregung... habe mal einbischen umgestöpselt und festgestellt, dass der Switch der dazwischen hängt mir wohl meine Packete verschluckt hat!
Mein Netzwerk:

Server----->WLAN AP >>>>>>>>>>>>> WLAN AP --> Switch --> Clients

Wenn ich den Switch rausnehme habe ich auf jeden Fall ein Bild wie ich es erwarte!!!

Wie gesagt bin sehr neu in diesem Thema und hätte nicht erwartet das ein Switch mir Packete verschluckt...

Achja was ich erreichen will ist:
Ich will vom Client Objekte verschicken die beim Server zu Bilder verarbeitet werden und angezeigt (Video)...
Ein Beispiel:
Ein kleines Ferngesteuertes Auto mit einer CAM soll anhand des Video gesteuert werden können

5.742 Beiträge seit 2007
vor 11 Jahren

Streaming Protokolle wie RTP basieren auf UDP, verhindern aber den Paketverlust, ohne, dass alle Pakete wieder geschickt werden, sondern nur das verlorene Paket.

Wobei dann aber der Kommunikationscode entsprechend angepasst werden muss, um genau diese Szenarien zu unterstützen - und das scheint der OP nicht gemacht zu haben.

Wie gesagt bin sehr neu in diesem Thema und hätte nicht erwartet das ein Switch mir Packete verschluckt...

Genau damit muss man in Netzwerken aber jederzeit rechnen; und gerade mit UDP führen Paketverluste eben dazu, dass die Daten dann gar nicht in deinem Programm ankommen.

Ich will vom Client Objekte verschicken die beim Server zu Bilder verarbeitet werden und angezeigt (Video)...

Da würde ich an deiner Stelle Ausschau nach fertigen Komponenten zum Videostreaming halten, z.B. Streaming over HTTP with JavaScript: AJAX video player oder Live c# video streaming webcam server and client

156 Beiträge seit 2010
vor 11 Jahren

Moin,

Ein kleines Ferngesteuertes Auto mit einer CAM soll anhand des Video gesteuert werden können

Da Du an der Stelle eigentlich kein Zeitversatz gebrauchen kannst (Buffering), wird Dir nichts anderes übrig bleiben die Paket selber über UDP zu verschicken. Dabei musst Du dann jedoch damit leben das Paket (somit Teile des Bildes verloren gehen). Wenn Du die Größe der UDP-Pakete kleiner als MTU-Größe wählst ist das nicht tragisch.

hand, mogel