Laden...

TCP Socket Client mehrmals mit Server verbinden mithilfe von Threads oder Async Await

Erstellt von Olii vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.446 Views
O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren
TCP Socket Client mehrmals mit Server verbinden mithilfe von Threads oder Async Await

Hallo, ich spiele momentan mit Theads und Async Await herum, bin aber noch sehr unsicher mit diesen Themen.

Was ich gerade versuche ist folgendes:

Ich habe einen kleinen TCP Server programmiert der einfach nur Client Anfragen entgegennimmt und einen String zurück sendet.

Was ich jetzt gerne probieren möchte ist, den selben Client, mehrmals mit dem Server zu verbinden, um z.B. mehrere Prozesse gleichzeitig anzustoßen (wie gesagt nur ein Testprojekt).

Ich kann mich mit dem Server verbinden und bekomme auch den String zurück, mit dem kleinen Stück Code den ich erstellt habe:


void sendData()
        {
            master.Send(System.Text.Encoding.UTF8.GetBytes(txtMsg.Text));

            int readByte;

            byte[] Buffer = new byte[master.SendBufferSize];

            readByte = master.Receive(Buffer);
            byte[] rData = new byte[readByte];
            Array.Copy(Buffer, rData, readByte);

            string test = System.Text.Encoding.UTF8.GetString(rData);

            txtText.Text += test + Environment.NewLine;
        }

Das funktioniert auch ganz gut.

Nur was sollte man lieber benutzen für mehrere Verbindungen?
Threads: Z.B. die Methode mehrmals mit Task.Run(sendDate) ausführen

oder

Async Methoden die "einfach" "gleichzeitig" ausgeführt werden und mit z.B. einem WaitAll() am Ende abgefragt werden?

Ich habe gelesen das man mit Threads vorsichtig sein soll und bloß nicht zu viele erstellt. Mit Async passiert es allerdings ja nicht wirklich "gleichzeitig".

Hat jemand ein paar Erfahrungsberichte?

Danke von olli 😃

16.806 Beiträge seit 2008
vor 4 Jahren

Du vermischt hier paar Dinge:

  • Threads vs Tasks
  • TCP Client
  • Software Architektur

Threads vs Tasks
In 99,99% der Fälle ist in .NET die bessere Wahl Tasks zu verwenden.
Viel einfacher zu managen.

Für das Managene der parallelen Verbindungen ist es aber irrelevant, ob Threads oder Tasks.

Ich habe gelesen das man mit Threads vorsichtig sein soll und bloß nicht zu viele erstellt. Mit Async passiert es allerdings ja nicht wirklich "gleichzeitig".

Die Frage danach zeigt aber, dass Du das evtl. noch nicht so ganz verstanden hast, wofür das eigentlich ist 😉

Async/Await hat nichts mit paralleler Programmierung zutun - sondern mit asynchroner Programmierung.
Das sind durchaus zusmmenhängende Konzepte, aber eben keine identischen Konzepte.

Tasks und Threads haben grundlegend durchau das gleiche Ziel - auch wenn sich mehrere Tasks einen Thread teilen können.

Bei async/await und damit der asynchronen Programmierung geht es aber nicht um Parallelisierung, sondern eben um die asynchrone Umsetzung.

Wenn Du alles richtig machst, hast Du beide Konzepte in Deiner Idee umgesetzt.
TCP Client
Wenn Du den Overhead von TCP Clients vermeiden willst, was man meistens möchte, dann such Dir Abstraktionen.

Ein Chat zB ist Wunderbar mit WebSockets (SignalR) oder gRPC umzusetzen und nimmt einem alle Themen, die so aufkommen, ab.
Die Implementierungen in .NET können dabei auch mehrere Verbindungen zeitgleich verwalten, wobei man das prinzipiell wegen dem Overhead vermeiden sollte.

Software Architektur
Man verschmischt nicht an "irgendwelchen Stellen" Quellcode-Logik mit Infrastruktur.
Das Senden sollte an für sich schon asynchron sein; die gesamte Verbindungshaltung sollte dann aber getrennt sein - sollte es mehrere Verbindungen geben sollen.
In der Objektorierntierten Programmierung gibts dafür Klassen:
Mehrere Verbindungsinstanzen, mehrere Instanzen Deiner Klasse.

public class MyChatConnection
{
   private TcpClient _myIsolatedTcpClientConnection...
}
public IList<MyChatConnection> Connections ...
O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren

Danke für die Antwort hab. Ich finde es Klasse wie du immer noch Tipps mit der Architektur gibst, sowas ist generell echt super (mein Ausbilder weiß wahrscheinlich nicht einmal was das so genau ist anscheinend. Ich hab mir Dinge von im abgeguckt die ich hätte besser ein lassen sollen, wie z.B. alles an Logik immer hinter eine Form zu packen ^^, aber das tut hier ja nichts zu Sache).

Threads vs Tasks
So wie ich das verstanden habe sind Task die Aufgaben und Threads diejenigen die die Aufgaben ausführen. Immer wenn ich ein Task.Run mache, zeigt mir VIsual Studio an das entweder ein Threadpool thread verwendet wird oder ein neuer Thread erstellt wird. Deswegen dachte ich es macht in der Beschreibung keinen unterschied wie ich es bezeichne.

TCP Client
Eine Chat wollte eigentlich nicht machen, ich dachte mehr an eine Schnittstelle die über TCP verschiedene Aktionen ausführt wenn man diese anspricht. Oder ein TCP Endpoint der je nachdem was man sendet eine bestimmte Aktion ausführt und eine Rückantwort sendet sobald die Aufgabe abgeschlossen ist.

Und für so einen Fall wollte ich mal versuchen, dass ein Client mehrere Aktion "gleichzeitig" anstößt, ohne darauf zu warten ob ein Client Socket bereits eine Antwort vom Server erhalten hat. Ich dachte ein Extra Framework oder etwas dergleichen wäre vielleicht ein Overkill für eine "vermeindlich einfache Sache".

"Das Senden sollte an für sich schon asynchron sein"

  • Macht es denn einen unterschied wenn man das mit Task machen würde? Ich spiele gerade ein wenig herum und wenn ich einen Task verwende, läuft der ja sowieso getrennt von dem Main Thread und blockiert nicht.
16.806 Beiträge seit 2008
vor 4 Jahren

So wie ich das verstanden habe sind Task die Aufgaben und Threads diejenigen die die Aufgaben ausführen. Immer wenn ich ein Task.Run mache, zeigt mir VIsual Studio an das entweder ein Threadpool thread verwendet wird oder ein neuer Thread erstellt wird.

Okay, das zeigst: Du hast keine Ahnung was Tasks und was Threads sind 😃
Dringender Nachholbedarf, denn durch das Missverständnis hast Du auch den völlig falschen Implementierungsansatz.

Vereinfacht:
Prozesse und Threads sind Elemente, die Dir das Betriebssystem zur Verfügung stellt - egal ob Du mit Java, .NET, C++.... arbeitest.
Ein Prozess und ein Thread stellen beides im Prinzip ein Stück "Arbeit" dar, das abgearbeitet werden muss.
Diese Dinge verwaltet das Betriebssystem.

Tasks sind ebenfalls Abstraktionen von Arbeit, werden aber von der .NET Runtime verwaltet.
Das Betriebssystem kennt aber "Tasks" nicht, sondern nur die .NET Runtime.

Jeder Task ist einem Thread zugeordnet, das macht alles der Task Scheduler für Dich - daher in Visual Studio auch Deine Beobachtungen.
Ein Task kann aber den Thread wechseln und ein Thread kann für mehrere Tasks verantwortlich sein.

Grund: Threads allokieren Betriebssystemressourcen und .NET versucht durch den Scheduler das Thread Handling zu vereinfachen und insgsamt viel effizienter zu gestalten.
Das ist alles sehr komplex unter der Haube, daher sehr vereinfacht ausgedrückt.

Threads und Tasks sind beides Dinge, mit denen man Arbeit parallelisieren kann.
Die Art und Weise unterscheidet sich aber teilweise sehr; und in .NET sollte man wenn möglich immer Tasks verwenden (mit ganz wenigen Ausnahmen).

Der Pattern für asynchrone Programmierung basiert in .NET auf Tasks - nicht auf Threads.
Mit asynchroner Programmierung versucht man, dass Code (und im Prinzip drunter) Threads nicht blockieren, und so die Systemressourcen effizienter verwendet werden können.

ich dachte mehr an eine Schnittstelle die über TCP verschiedene Aktionen ausführt wenn man diese anspricht. Oder ein TCP Endpoint der je nachdem was man sendet eine bestimmte Aktion ausführt und eine Rückantwort sendet sobald die Aufgabe abgeschlossen ist.

Da bist Du ebenfalls mit TCP viel zu tief.
Willst Du wirklich alle Bestandteile einer solchen Schnittstelle (Typisierung, Protokoll, Schema, Authentifizierung, Connection Management, Authorisierung...) selbst übernehmen?
Total unnötig (meistens) - meistens dafür fehlerhaft programmiert.

Verwende Standards! Und für sowas gibt es HTTP basierte APIs wie WebSockets, REST, gRPC.
Kein Grund das Rad neu zu erfinden.

Macht es denn einen unterschied wenn man das mit Task machen würde? Ich spiele gerade ein wenig herum und wenn ich einen Task verwende, läuft der ja sowieso getrennt von dem Main Thread und blockiert nicht.

Richtig.
Der Task Scheduler erstellt Dir einen Task in einem extra Thread, in dem dann Dein asynchroner Aufruf läuft.
Sobald dieser fertig ist beendet die sogenannte State Machine den Task und schickt Dich zurück in den Main Thread.

Der Pattern funktioniert in der Form in .NET mit async/await nur mit Tasks - und das ist gut so.

Daher:

  • Vergess erstmal Threads, Du wirst vermutlich so schnell nicht in den Bereich kommen, dass Du Dich direkt mit Threads und deren Overhead rumärgern musst. Nutze die vereinfachte Abstraktion von Tasks, die Dir das Framework schenkt.
  • Erfinde keine Kommunikationsprotokolle neu, wenn Du es nicht brauchst (und kaum ein Entwickler wird das in seinem Entwicklerleben jemals brauchen)
O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren

Danke Abt für die super Erklärung!

Das Thema ist komplizierter als ich gedacht habe. Ich dachte ich hätte es nun gerafft nach 4 Wochen aber, ich setzt mich noch einmal ran. Ich möchte das auf jeden Fall komplett verstehen. Das ist denke ich ein Thema, das man immer gut gebrauchen kann.

Da bist Du ebenfalls mit TCP viel zu tief.

Ich bin etwas schlecht darin mich richtig auszudrücken manchmal, muss ich auch noch üben 😄.
Was ich eher meinte das ich eigentlich das ich mit System.Net.Sockets arbeiten wollte. Also Client Sockets die sich zu mehrfach vom selben Programm aus mit einem SocketServer verbinden und verschiedene Dinge abarbeiten. Der Server-Socket wäre in dem Fall ein Windows-Dienst der auf einer VM läuft (existiert bereits und kann/darf nicht angepasst werden).

EDIT: Dieser Dienst ist schon uralt, aber leider noch nicht ersetzbar (von 1995). Deswegen glaube ich nicht das der Socket Server mit Websockets klar kommen würde. Websocket baut anscheinden auf dem plain Socket (TCP) auf. Aber die Server Schnittstelle müsse sowas ja dann auch verarbeiten können, wo ich mir nicht sicher bin bei einem so alten Service.

Es gibt ja noch Systems.Net.Websockets, das wird wenn ich das richtig gelesen habe in ASP.NET /Core verwendet und dachte dass das eher so für den das "richtige" Web geacht ist und ich mit meinen Basteleien nur im eigenen Netzwerk befinde.

Vielleicht gibt es da auch andere Unterschiede, ich werde mal versuchen mehr darüber herauszufinden, wann welche davon verwendet werden sollte.
EDIT: Unterschied zwischen Socket und Websockets

Was ich zu dem Thema halt von MS mir genommen habe sind die Beispiel Implementierungen von Net.Sockets, mit denen ich gerade herumspiele um zu sehen wie die funktionieren:

Async Client Socket

Erfinde keine Kommunikationsprotokolle neu, wenn Du es nicht brauchst

Selbst wenn ich es brauchen würde, wäre ich noch zu doof dafür 😄 da bin ich denke ich noch weit weg von

Danke auf jeden Fall nochmal für deine Hilfe. Ich weiß das sehr zu schätzen das du deine Zeit dafür investiert hast. Ich wünschte ich könnte irgendwas zurück geben. Mal gucken ob man hier Spenden kann.

16.806 Beiträge seit 2008
vor 4 Jahren

Was ich eher meinte das ich eigentlich das ich mit System.Net.Sockets arbeiten wollte.

Aber wieso tust Du Dir das freiwillig an? Lerneffekt?
Macht selten Sinn das Rad neu zu erfinden und damit eben oft die Security zu vernachlässigen - geschweige denn von Standards zu missachten.

Es gibt ja noch Systems.Net.Websockets, das wird wenn ich das richtig gelesen habe in ASP.NET /Core verwendet und dachte dass das eher so für den das "richtige" Web geacht ist und ich mit meinen Basteleien nur im eigenen Netzwerk befinde.

Dann les Dir das besser nochmal durch 😉
WebSockets können überall verwendet werden.

Mal gucken ob man hier Spenden kann.

Spende bitte besser an die Kinderkrebshilfe oder an ein Kinderhospiz 😃
Die brauchen das dringender und da ist das Geld besser aufgehoben.

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren

Ich habe mal versucht so etwas mit WebSockets zu basteln.

Ich hab das mal hier im Forum unter Review gepostet:

mycsharp.de Code Review