[Winsocks] Über Threads mehrere Objekte gleichzeitig senden?



  • Hi,

    ich hab mir letztens eine Socket-Wrapper-Klasse zusammengebastelt, also eine CClient und eine CServer.

    Ist nun schön und gut, doch ich frag mich, ob es möglich ist, einzelne Teile in Threads zu packen und gleichzeitig mehrere Daten mit einem Socket zu verschicken.

    Beispiel:

    Thread1:
    Schickt alle 30 Sekunden eine Ping Nachricht
    und warten dann auf eine Pong Nachricht.
    Falls diese nicht kommt, wird eine (WM_USER+...) Nachricht
    an den Hauptthread verschickt.

    Thread2:
    Sendet Objekt Request,
    bekommt dann ein Objekt Response
    und schickt zu guter letzt ein Objekt Confirmation.
    (Der Thread wird dann immer wieder pausiert und nur benutzt, wenn wirklich was zum Senden ansteht.)
    Thread3:
    Sendet oder Erhält irgend was anderes.

    Ist es nun möglich, dass während ich
    send(s,&reinterpret_cast<char*>whatever,sizeof(whatever)) mach auch gleichzeitig
    send(s,..ping,...);
    recv(s,..pong,...);
    machen kann?^^

    Denk nämlich dass es irgendwie nicht geht, weil der Server würde ja nicht wissen, ob er beispielsweise das Pong an recv vom Thread1 oder vom Thread2 schicken würde, falls gleichzeitig eins ansteht. Falls doch, wunderbar.

    Aber falls nicht, gibt es da ne andere Lösung, zum Beispiel, dass ich dann mehrere Client-Socks und Server-Socks erstellen, die jeweils zu nem anderen Port gehören?
    Oder wäre es vllt am besten, das ganze über Synchronisations-Objekte zu realisieren, sprich, wenn einer was sendet bzw. was empfängt, steht für die anderen nichts an.



  • hola

    wenn du dir ein eigenes protokol entwickelst, dann funktioniert das schon.

    Meep Meep



  • Du kannst mal versuchen für jeden Thread eine Socketverbindung zu erstellen.
    Damit könntest du vieleicht sogar Geschwindigkeit gut machen.



  • Also über TCP oder UDP funkt das dann anscheinend nicht?



  • markusrw schrieb:

    Also über TCP oder UDP funkt das dann anscheinend nicht?

    doch. nur musst du dir halt selbst ein protokol stricken, damit du weißt wann was wie ankommt

    Meep Meep



  • das was du da oben schreibst hoert sich viel zu kompliziert an



  • Also spontan fällt mir nur folgendes ein, wie ich regeln kann, dass ich weiß, wann was wie an kommt^^

    Ich schicke immer eine Art Kontrollstring an meinen Hauptthread, der die nächste Aktion vorraussagt, wodurch ich aber dann trotzdem nicht gleichzeitig Aktionen ausführen kann. Hmm.

    Kann ich den mehrere (Clienten und Server) Socks auf einem Rechner unter dem gleichen Port laufen lassen, sozusgaen folgendes:
    s[0] läuft auf port 123456
    s[1] läuft auf port 123456

    usw.

    Aber ich glaube, dann hätte ich wieder ein Problem mit dem Empfangen von Nachrichten. Hat jemand vllt doch eine Lösung parat?^^

    Also meine Überlegung ist bisher so:

    c.send() -> s.recv() -> s.send() -> c.recv()
    

    Das hier wäre ja normalerweiße der Ablauf, kein Problem.

    thread1:
    c.send()-> s.recv() -> s.send() -> c.recv()
    thread2:
    c.send()-> s.recv() -> s.send() -> c.recv()
    

    Dies wäre ja optimal.

    thread1:
    c.send()-  -> s.recv()---->s.send()-  ->c.recv()
    thread2: \/                         \/
    c.send()-/\-> s.recv()---->s.send()-/\->c.recv()
    

    Das ist mein Problem^^
    Nochmal in Wort gefasst:
    Ich glaube, dass wenn ich den gleichen Socket in zwei Threads zum Senden verwende, ich nicht garantieren kann, wie recv es empfangen soll und nicht eventuell ein-zwei daten von den jeweiligen ping-pong-threads in den vi-p-thread gelangen und dadurch alles total versaut wird.^^

    Ahja c= client, s = server^^



  • Dann muss deine Socket-Klasse erkennen welches Paket kommt (Protokoll!) und es an den zuständigen Thread weiterleiten.



  • Yupp, dass weiß ich auch, aber mir fällt momentan partu nicht ein, wie. 😕



  • Durchnummerieren zum Beispiel:

    0 - Ping
    1 - Pong
    2 - Request
    usw.

    Wo genau liegt dein Problem?



  • Es soll ja asynchron laufen^^
    Weil das, was du mir grad gezeigt hast, folgt ja sozusagen einer Linie.^^

    frage?->antwort->frage->antwort...

    aber was ist, wenn zwei threads gleichzeitig laufen:
    frage->antwort----->frage->....
    frage->antwort->frage->antwort->..

    Dies meine ich^^

    Ich glaube mir bleibt wohl wirklich nichts anderes übrig, als über verschiedene Ports zu machen oder das ganze immer kurzhintereinander laufen zu lassen und somit wieder zum Frage->Antwort-Spiel zurückzukehren.^^



  • Dann musst du es asynchron machen!

    Wenn über den Socket ein Paket kommt ist erstmal nicht klar, um was für ein Paket es sich handelt. Du solltest wenn du ein Paket versendest so etwas wie eine ID für des Paket und die Länge des Paketes senden, da nicht gewährleistet ist, dass ein Paket immer in einem Stück ankommt.

    Folgendes Beispiel:
    Du hast 2 Threads die Daten über einen Socket versenden und du hast einen Thread in dem der Socket läuft. Der Socketthread wird so lange blockiert bis Daten kommen.
    Es werden dann z.B. zuerst 5 Bytes (1 Byte ID + 4 Byte für Paketlänge) gelesen, mit der empfangenen Länge weiß er auf wie viel Daten er warten muss. Sind alle Daten angekommen werden sie anhand der ID weitergeleitet. Der Socketthread wird wieder blockiert bis das nächste Paket eintrifft.



  • joa an das mit der id hab ich auch schon gedacht, aber ich weiß net, wie ich da eine eindeutig zuordnen soll, ich könnte in meiner klasse vllt einen count anlegen, der immer wieder inkrementiert wird, wenn ein paket versendet wurde:

    Nachteil nur, dass der Server dann nicht mehr damit auskommt, weil der ja mit den gleichen IDs arbeitet, was vllt noch gehn würde, wäre die Zeit als ID oder was meint ihr?

    Was mir auch noch so einfällt:
    Client sendet fünf Pakete, count=5;
    Server empfängt fünf Pakete, count = 5;
    Client neustart
    Client count = 0;
    gleich am Anfang könnte ich eine Anfrage an den Server schicken, wodurch ich dann den Wert lade und count dann auch gleich 5 ist.

    Aber ich glaub ich mach das jetzt mal so:

    bool Client::send(const Request& r)
    {
       header<Request> h = r;
       this->sendHeader(h);
       recv(...); -> bestätigung
       this->sendRequest(r);
    }
    

    Ahja das soll jetzt nur ein Beispiel sein, wie ich es genau mach, muss ich mir noch überlegen.

    Naja so hab ich jetzt das Problem mit der Identifizierung gelöst, aber das mit dem gleichzeitigen Versenden noch nicht.
    Ich könnte es ja vllt so probieren:
    1. Header mit der ID und der Größe der ersten Datei wird verschickt.(Thread 1)
    2. Header mit der ID und der Größe der zweiten Datei wird verschickt.(Thread 2 / 100 mSec Verzögerung)
    3. Datei 1 wird verschickt. (Thread 1)
    4. Datei 2 wird nach 100mSekunden auch verschickt. (Thread 2)

    Ist gewährleistet, dass die Pakete auch am richtigen Ort ankommen, wenn ich es so mache, oder kann es passieren, dass irgendwas undefiniertes passiert.^^

    Ich mein ja nur, woher will das Paket wissen, zu welche recv() es hin soll, wenn ich den gleichen Socket mit gleichen Eigenschaften verwende. (Weil wie schon gesagt wurde, es kann ja sein, dass nicht alle Daten auf einmal verschickt werden können und deshalb muss es ja nochmal verschickt werden und wäre blöd, wenn da dann irgendwas durcheinander gerät^^)

    Vllt sollte ich mir auch einfach die WSAAsync-Funktionen anschaun, vllt ist es ja das, was ich suche.^^



  • edu hast ein völlig falsches konzept, deshalb macht dieser thread auch so wenig sinn. so wirst du es machen: thread1 pennt auf recv und ggf aufm timer und der andere arbeitet.



  • Joa meine frage war ja eigetnlich, ob ich mit einem Socket, zwei Nachrichten gleichzeitig senden kann und anscheinend geht es irgendwie, aber ist viel zu kompliziert.^^

    Deshalb werd ich es wohl entweder so machen, dass ich durch ein Event das ganze in den Threads synchronisiere oder verschiedene Ports nehme, wenn ich beispielsweise alle 30 Sekunden ein ping-pong machen will, dann noch währenddessen eine Datei verschicken will und dann noch über ein anderen Thread Befehle verschicke, die irgend etwas am Server machen.

    Aber naja, kann schon geschlossen werden, falls es da keine Möglichkeit gibt.^^



  • Du solltest dich mal davon verabschieden, dass alles absolut synchron laufen muss. Sende eins nach dem anderen und empfange eins nach dem anderen, dann klappt das.



  • Wieso verabschieden, ich habs ja noch net mal begrüßt ;P

    Wäre nett gewesen, falls es geklappt hätte, aber ein Beinbruch ist es doch auch nicht.
    So erstell ich halt mehrere Sockets für jeden Thread und mach alles nacheinander.^^


Log in to reply