Netzwerk mit Boost, Server mit mehreren verbindungen



  • Hi Leute,

    wenn man einen TCP-Server schreiben möchte und dabei davon asugeht, dass gleichzeitig mehrere Clients bedient werden müssen, muss dann für jeden dieser clients ein eigener socket angelegt werden oder reicht es einen Socket anzulegen und nur die endpoints der clients zu verwalten, sodass der Datentransfer komplett über einen socket läuft? Gibts da überhaupt eine Faustregel oder ist das Fallabhängig? Konkret verwende ich die boost::asio Bibliothek.

    Angemerkt sei noch, dass nach einer etablierten Verbindung Daten auch ohne vorherige Anfrage des Clients gesendet werden sollen.





  • Hallo Freddy,

    aus der englischen Wikipedia (Socket): "A network socket is an endpoint of an inter-process communication flow across a computer network." - also endpoint und socket ist quasi das selbe. Und wenn die Clients nicht alle gemeinsam auf einem einzigen Computer sitzen, dann musst Du natürlich für jeden Client einen Socket haben.

    Schau Dir die Beispiele in der Doku zu boost.asio an. Für jeden Client ein "Connection"-Objekt - das würde ich als gegeben ansehen. Mit boost.asio kannst Du mehrere Verbindungen (Connections) mit natürlich je einem - also in Summe mehreren Sockets - in einem Thread bearbeiten (genau dafür ist es ja gemacht worden!).

    Gruß
    Werner



  • Pellaeon schrieb:

    Dazu reicht ein Socket. In der asio-Doku findest du Tutorials genau zu diesem Thema:

    http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/tutorial.html

    😕
    in den dort aufgeführten Beispielen (z.B. datime-Server) wird mit jedem neuen accept eine neue Verbindung mit neuem Socket bzw. bei dem synchronen Beispiel ein neuer Socket angelegt.



  • Es gibt mehr Moeglichkeiten mittels select, epoll etc. Bevor du zu Boost oder einer anderen Bibliothek greifst, rate ich dir, dich mit den Grundlagen vertraut zu machen: http://beej.us/guide/bgnet/

    sodass der Datentransfer komplett über einen socket läuft?

    Ja, dass ist moeglich. bzw. haengt es von Anwendungsfal und Umstaenden ab, was besser ist.



  • Pellaeon schrieb:

    Dazu reicht ein Socket. In der asio-Doku findest du Tutorials genau zu diesem Thema:

    http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/tutorial.html
    http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/examples.html

    Es werden in allen Beispielen jeweils ein socket / connection verwendet ;).

    Werner Salomon schrieb:

    Hallo Freddy,

    aus der englischen Wikipedia (Socket): "A network socket is an endpoint of an inter-process communication flow across a computer network." - also endpoint und socket ist quasi das selbe. Und wenn die Clients nicht alle gemeinsam auf einem einzigen Computer sitzen, dann musst Du natürlich für jeden Client einen Socket haben.

    Schau Dir die Beispiele in der Doku zu boost.asio an. Für jeden Client ein "Connection"-Objekt - das würde ich als gegeben ansehen. Mit boost.asio kannst Du mehrere Verbindungen (Connections) mit natürlich je einem - also in Summe mehreren Sockets - in einem Thread bearbeiten (genau dafür ist es ja gemacht worden!).

    Gruß
    Werner

    Dass es dasselbe ist sehe ich so nicht. ein Socket ist ein tupel bestehend aus localIP, localPort, remoteIP, remotePort und protocol. Hat also egtl 2 Enpoints, wobei sich bei mir nur der RemoteEndpoint bei den Verbindungen unterscheidet.

    Ich kann natürlich strikt nach den Beispielen vorgehen, will das aber selbst machen, da das Verständnis dann deutlich besser ist. Im übrigen wollt ich wissen obs einen Grund gibt auf mehrere sockets zu verzichten.



  • Hallo Pellaeon, hallo knivil,

    klärt mich doch mal auf - ich lerne ja gerne hinzu! - wie läuft der Datenverkehr von zwei Clients (auf zwei unterschiedlichen Netzknoten versteht sich) über einen einzigen Socket?
    Oder postet den Link auf ein entsprechendes Beispiel in boost.asio oder sonst wo.

    Gruß
    Werner



  • Freddy_Kay schrieb:

    Pellaeon schrieb:

    Dazu reicht ein Socket. In der asio-Doku findest du Tutorials genau zu diesem Thema:

    http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/tutorial.html
    http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/examples.html

    Es werden in allen Beispielen jeweils ein socket / connection verwendet ;).

    Hmm !? - vielleicht meinen wir mit 'Socket' verschiedene Dinge.
    Nehmen wir doch mal ganz konkret das Beispiel zum asynchronen DayTimeServer - siehe http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/tutorial/tutdaytime3.html.
    Dort wird ein server -Objekt angelegt. Im Konstruktor des server s wird start_accept gerufen. In start_accept wird ein neues(!) Objekt der Klasse tcp_connection angelegt, die ein boost::asio::socket -Objekt als Member enthält.
    Unter der Annahme, dass sich hinter dem boost::asio::socket eine Socket-Struktur des Betriebssystem verbirgt, kommt mit jeder Verbindung ein neuer Socket dazu.

    Bei dem synchronen Beispiel ist es ähnlich (http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/tutorial/tutdaytime2.html). Nur das dort immer nur genau ein socket gerade zu einer Zeit aktiv ist. Es ist ein lokales Objekt in einer for-schleife.

    oder sehe ich das falsch?

    Gruß
    Werner



  • Werner Salomon schrieb:

    Freddy_Kay schrieb:

    Pellaeon schrieb:

    Dazu reicht ein Socket. In der asio-Doku findest du Tutorials genau zu diesem Thema:

    http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/tutorial.html
    http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/examples.html

    Es werden in allen Beispielen jeweils ein socket / connection verwendet ;).

    Hmm !? - vielleicht meinen wir mit 'Socket' verschiedene Dinge.
    Nehmen wir doch mal ganz konkret das Beispiel zum asynchronen DayTimeServer - siehe http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/tutorial/tutdaytime3.html.
    Dort wird ein server -Objekt angelegt. Im Konstruktor des server s wird start_accept gerufen. In start_accept wird ein neues(!) Objekt der Klasse tcp_connection angelegt, die ein boost::asio::socket -Objekt als Member enthält.
    Unter der Annahme, dass sich hinter dem boost::asio::socket eine Socket-Struktur des Betriebssystem verbirgt, kommt mit jeder Verbindung ein neuer Socket dazu.

    Bei dem synchronen Beispiel ist es ähnlich (http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/tutorial/tutdaytime2.html). Nur das dort immer nur genau ein socket gerade zu einer Zeit aktiv ist. Es ist ein lokales Objekt in einer for-schleife.

    oder sehe ich das falsch?

    Gruß
    Werner

    Du siehst das richtig ich meinte: Es werden in allen Beispielen jeweils ein socket PRO connection verwendet ;).



  • Werner Salomon schrieb:

    Pellaeon schrieb:

    Dazu reicht ein Socket. In der asio-Doku findest du Tutorials genau zu diesem Thema:

    http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/tutorial.html

    😕
    in den dort aufgeführten Beispielen (z.B. datime-Server) wird mit jedem neuen accept eine neue Verbindung mit neuem Socket bzw. bei dem synchronen Beispiel ein neuer Socket angelegt.

    Hast recht, da war ich zu voreilig 😞 . Der ioService wird geteilt, nicht der Socket. Man kann auf einem Port mehrere eingehende Verbindungen verwalten, aber in den asio-Tuts hat man dafür immer ein neues Socket-Objekt.

    VG

    Pellaeon



  • Werner Salomon schrieb:

    wie läuft der Datenverkehr von zwei Clients (auf zwei unterschiedlichen Netzknoten versteht sich) über einen einzigen Socket

    Man erstellt einen Socket und macht ein bind/listen im Falle von TCP. Einhgehenden Verbindungen benutzen diesen um zu connecten. Bei accept/connect wird daraus ein neuer abgeleitet. Benutzt man kein TCP sondern bspw. UDP dann laufen nicht nur die Verbindungsabffragen ueber einen Socket, sondern vielleicht der gesamte Datenverkehr.



  • Hallo Freddy,

    Freddy_Kay schrieb:

    ... ich meinte: Es werden in allen Beispielen jeweils ein socket PRO connection verwendet ;).

    Ok - ich hatte das eher als "nur ein socket und nur eine connection" interpretiert.

    Freddy_Kay schrieb:

    Dass es dasselbe ist sehe ich so nicht. ein Socket ist ein tupel bestehend aus localIP, localPort, remoteIP, remotePort und protocol. Hat also egtl 2 Enpoints, wobei sich bei mir nur der RemoteEndpoint bei den Verbindungen unterscheidet.

    Das ist mir bekannt, nur wie willst Du einen Endpoint ohne Socket ansprechen? Oder mit einem Socket ansprechen, der auf einen anderen Endpoint zeigt - Wie funktioniert so was?

    Knivil behauptet ja auch, dass das geht - siehe auch http://www.c-plusplus.net/forum/p2246404#2246404
    .. würde mich mal interessieren.

    Gruß
    Werner



  • knivil schrieb:

    Werner Salomon schrieb:

    wie läuft der Datenverkehr von zwei Clients (auf zwei unterschiedlichen Netzknoten versteht sich) über einen einzigen Socket

    Man erstellt einen Socket und macht ein bind/listen im Falle von TCP. Einhgehenden Verbindungen benutzen diesen um zu connecten. Bei accept/connect wird daraus ein neuer abgeleitet.

    Ja klar, genauso gehe ich auch vor - nur mit mit dem ".. wird daraus ein neuer abgeleitet" hast Du doch mehr als einen - oder?
    Und mit dem einen Socket kann doch auch nur mit einem Client reden. Nach einem neuen accept gebe ich die eventuell bestehende Verbindung doch auf, wenn ich vorher keinen neuen davon abgeleitet habe.



  • Server
    tcp: socket (create socket for listening) -> bind -> listen -> accept (get a socket for that connection)
    udp: socket -> bind -> recvfrom (client identification through metainformation from udp packet)

    Und ja, ich habe mehr als einen. Beim Vorgehen ist man an die Api/Framework gebunden.

    Nach einem neuen accept gebe ich die eventuell bestehende Verbindung doch auf, wenn ich vorher keinen neuen davon abgeleitet habe.

    Nein, ein accept leitet immer einen weiteren Socket ab, bestehende werden nicht terminiert, ausser du verwendest die gleiche Variable und ueberschreibst diese (keine Ahnung, ob es ein Fehler gibt). Aber prinzipiell kann man bei TCP nur einen Socket pro Verbindung haben bzw. eine Verbundung pro Socket haben. Im Fall von TCP hast du recht, doch es ist ... komplizierter.



  • Werner Salomon schrieb:

    Hallo Freddy,

    Freddy_Kay schrieb:

    ... ich meinte: Es werden in allen Beispielen jeweils ein socket PRO connection verwendet ;).

    Ok - ich hatte das eher als "nur ein socket und nur eine connection" interpretiert.

    Freddy_Kay schrieb:

    Dass es dasselbe ist sehe ich so nicht. ein Socket ist ein tupel bestehend aus localIP, localPort, remoteIP, remotePort und protocol. Hat also egtl 2 Enpoints, wobei sich bei mir nur der RemoteEndpoint bei den Verbindungen unterscheidet.

    Das ist mir bekannt, nur wie willst Du einen Endpoint ohne Socket ansprechen? Oder mit einem Socket ansprechen, der auf einen anderen Endpoint zeigt - Wie funktioniert so was?

    Knivil behauptet ja auch, dass das geht - siehe auch http://www.c-plusplus.net/forum/p2246404#2246404
    .. würde mich mal interessieren.

    Gruß
    Werner

    Naja zu Beginn habe ich mich gefragt ob es zwingend nötig ist für jede Connection ein eigenes "socket-Objekt" zu verwalten (mit allem was dazugehört), also ob sie für jede Verbindung einzigartig sein müssen, oder ob es "quasi" ein globales Socket Objekt geben kann dessen RemoteAdresse immer so gesetzt wird, dass der Richtige Client bedient wird. Also für jede Verbindung würde das entsprechende endpoint-objekt verwaltet.



  • Und was hast du durch die bisherigen Antworten erfahren? Welche Unklarheiten gibt es?



  • Freddy_Kay schrieb:

    Dass es dasselbe ist sehe ich so nicht. ein Socket ist ein tupel bestehend aus localIP, localPort, remoteIP, remotePort und protocol. Hat also egtl 2 Enpoints, wobei sich bei mir nur der RemoteEndpoint bei den Verbindungen unterscheidet.

    Was du beschreibst ist kein Socket, sondern eine Connection.
    Ein Socket ist ein etwas abstrakteres Ding.

    Aber um es kurz zu machen: wenn du nen Server hast, der mehrere TCP Connections gleichzeitig bedienen kann, dann brauchst du einen Socket um Verbindungen anzunehmen (den "Server Socket"), und pro Verbindung nochmal einen extra Socket.


Log in to reply