Forum: Mikrocontroller und Digitale Elektronik TCP/UDP Antworten vom Server zum Client


von brechbunkt (Gast)


Lesenswert?

Hallo,

ich sehe mir gerade dieses Beispiel zum Erstellen von Server und Client 
per TCP an:
http://www.c-worker.ch/tuts/wstut_op.php

Anstatt nach erfolgter Verbindung einen neuen thread zu starten, der 
diesen bedient, möchte ich es bei nur einem einzigen belassen. Somit 
kann auch nur ein Client mit meinem Server gleichzeitig verbunden sein.
Bei TCP ist die Verbindung fest geregelt. Bei UDP ist es aber so, dass 
jeder den Server "anschreiben" kann. Wie ist es dann aber bei Antworten 
VOM Server? Wird die Antwort dann an die IP geschickt, die die 
Verbindung zuerst aufgenommen hat?

von g457 (Gast)


Lesenswert?

> [..] UDP [..] Wie ist es dann aber bei Antworten VOM Server? Wird die
> Antwort dann an die IP geschickt, die die Verbindung zuerst aufgenommen
> hat?

Nein, natürlich nicht. Die Antwort geht an die Adresse, die Du angibst.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

brechbunkt schrieb:
> Bei UDP ist es aber so, dass
> jeder den Server "anschreiben" kann. Wie ist es dann aber bei Antworten
> VOM Server? Wird die Antwort dann an die IP geschickt, die die
> Verbindung zuerst aufgenommen hat?

Bei UDP gibt es keinen Zustand, den man "Verbindung" nennen könnte. Es 
werden Pakete (bei UDP "Datagramm" genannt), versendet, die entweder 
ankommen oder auch nicht. Da steht die Quelladresse drinnen. Wenn der 
Empfänger mag, kann er diese auslesen und eine Antwort senden ...

von brechbunkt (Gast)


Lesenswert?

Danke für die Antworten.

Frank Esselbach schrieb:
> Es werden Pakete versendet, die werden entweder ankommen
> oder auch nicht. Da steht die Quelladresse drinnen.
> Wenn der Empfänger mag, kann er diese auslesen und
> eine Antwort senden ...

Heißt das dann also, der erste Client der gesendet hat (somit seine 
Quelladresse bekannt ist) und dessen Nachricht der Server als erstes 
entgegen genommen hat, der bekommt dann immer die Antworten vom Server 
zurück?
(In meinem Fall kann nur ein Client bedient werden, da nur ein thread)

Ich habe das oben genannte Beispiel nun mit UDP umgesetzt. Während der 
Programmierung hatte ich immer per loopback getestet. Da war es 
verständlich, dass ich immer das richtig sende und empfange. Nun habe 
ich die Verbindung von meinem Linux-Rechnter aus ("nc [ip] [port]") am 
Windows-Server eröffnet und ohne am Windows die IP zu nennen kam die 
Antwort richtig zum Linux zurück. Zufall oder normal?

von Axel S. (a-za-z0-9)


Lesenswert?

brechbunkt schrieb:
> Heißt das dann also, der erste Client der gesendet hat (somit seine
> Quelladresse bekannt ist) und dessen Nachricht der Server als erstes
> entgegen genommen hat, der bekommt dann immer die Antworten vom Server
> zurück?

Nein.  <seufz>

Wenn dein Server den UDP-Socket erzeugt hat, dann hast du im folgenden 
zwei Möglichkeiten:

1. du rufst anschließend auf dem Socket connect() auf. Einer der 
Parameter von connect() ist die Zieladresse. Anschließend kannst du mit 
send() über den Socket Daten verschicken, die an diese Adresse gehen.

2. du rufst connect() nicht auf. Dann darfst du im folgenden auch nicht 
send() verwenden. Aber du kannst mit sendto() auf den Socket schreiben, 
wobei einer der Parameter für sendto() die Zieladresse ist.

sendto() ist übrigens auch im ersten Fall erlaubt. Damit kannst du 
Pakete "außer der Reihe" an eine andere Adresse schicken als die die du 
vorher mit connect() festgelegt hast.

Wie du das logisch handelst, bleibt vollkommen dir überlassen. Eine 
mögliche (und logische) Variante wäre, daß dein Server mit recvfrom() 
auf ein eingehendes Paket wartet.

Sobald eins kommt, hat er die Absendeadresse (die wird von recvfrom() 
zurückgegeben) und kann dann mit sendto() seine Antwort schicken. 
Anschließend wieder zurück zur Warteschleife.

Alles obige gilt so zumindest für die Linux-Implementierung der 
Berkeley-Sockets. Wie kompatibel WinSock ist, weiß ich nicht. 
Interessiert mich auch nicht. Windows ist keine Zielplattform für mich.

Noch ein Vorteil von Linux: Dokumentation. Das obige steht alles so in 
der Manpage zu udp(7)

von Stefan F. (Gast)


Lesenswert?

Stell Dir UDP wie eine Postkarte vor. Jemand schickt eine Nachricht 
irgendwo hin und hofft, dass sie auch ankommt.

Es gibt keine formelle Antwort. Es gibt keine Verbindung.

Ich schicke Dir "Hallo, wie geht es Dir".
Du schickst mir "Mir geht es gut", falls du dazu Lust hast und meine 
Frage erhalsten hast.

Deine Postkarte unterscheidet sich technisch nicht von meiner. Der 
Postbote kann nicht erkennen, welche der Karten die Frage und welche die 
Antwort war, es sei denn, er liest die Texte und interpretiert sie 
intelligent.

UDP ist aber weder intelligent, noch schaut es in die Nutzdaten hinein. 
Für UDP ist jede Nachricht einfach nur ein Datenpaket, dass von irgend 
jemandem irgend wohin gesendet wird.

Nichtmal die Port-Nummern haben für das Protokoll irgendeine Bedeutung. 
Jedes Paket hat

Sender-Adresse + Sender-Port
sowie
Empfänger-Adresse + Empfänger-Port

Die Port Nummern sind für das Netzwerkprotokoll jedoch völlig 
bedeutungslos.

Manche Programme senden etwas an Port X und erwarten die Antwort 
ebebnfalls auf Port X. Andere Programme hingegen handhaben das ganz 
anders, zum Beispiel DHCP.

von c-hater (Gast)


Lesenswert?

brechbunkt schrieb:

> Bei UDP ist es aber so, dass
> jeder den Server "anschreiben" kann.

Ja, es gibt keine Verbindung.

> Wie ist es dann aber bei Antworten
> VOM Server?

Wo es keine Verbindung gibt, gibt es auch keine Antworten, sondern nur 
Fragen. Zu einem Frage-Antwortspiel kann es erst werden, wenn deine 
Programmlogik eines daraus macht, also selber eine logische Verbindung 
zwischen Fragen und Antworten schafft.

> Wird die Antwort dann an die IP geschickt, die die
> Verbindung zuerst aufgenommen hat?

Die Antwort wird an die Adresse geschickt, die du angibst. Wenn das die 
ist, von der die zugehörige Frage kam, hast du in erster Näherung eine 
Art Verbindung geschaffen. Aber: ein zweiter Kommunikationspartner auf 
demselben Host bringt schon das Gebäude zum Einsturz.
Um auf UDP sowas wie ein Verbindung aufzusetzen, genügt es also nicht, 
eine IP-Adresse als Verbindungmerkmal zu speichern. Zusätzlich muß der 
Port gespeichert werden.
Das Problem ist nun, daß du den auf dem "Server" garnicht weisst, du 
kennst nur den Port, von dem die Frage gesendet wurde, das ist nicht 
notwendigerweise der Port, auf dem der Peer die Antwort erwartet.

Deine Programmlogik muß also sowohl auf dem "Client" als auch auf dem 
"Server" eine (übereinstimmende) Logik enthalten, nach der bestimmt 
wird, auf welchem Port der Peer die Antwort auf die Frage erwarten wird.

Im Übrigen gibt es bei UDP mit logischer Verbindung keinen "Client" oder 
"Server". Beide Peers sind eigentlich immer beides.
Zum dedizierten Client oder Server werden sie auch erst wieder durch 
deine Programmlogik, die sich dementsprechend zwischen Client und Server 
unterscheiden muß. Einer muß auf Fragen warten und nur reden, wenn er 
welche gestellt bekommt, das ist dann der Server. Der Client hingegen 
muß aktiv werden, er muß die Fragen stellen und damit die Kommunikation 
anstoßen.

von (prx) A. K. (prx)


Lesenswert?

Tipp am Rande: Mancher zieht daraus den Schluss, dass UDP nur für 
Botschaften sinnvoll ist, die keine hin-und-her Kommunikation 
darstellen. Und kann ziemlich daneben liegen. Ich hatte schon Beispiele 
von Client/Server-Anwendungen, die mit TCP völlig auf die Nase fielen 
und UDP den weit sinnvolleren Weg dargestellt hätte. Nicht immer ist die 
Transportabsicherung von TCP hilfreich, insbesondere wenn auf anderen 
Layern der Kommunikation ebenfalls schon eine solche stattfindet.

von Axel S. (a-za-z0-9)


Lesenswert?

Stefan us schrieb:
> Nichtmal die Port-Nummern haben für das Protokoll irgendeine Bedeutung.

Das stimmt so nicht. Die Portnummer ist Teil der Adresse. Ohne 
Portnummern könnte UDP nur genau einen Empfänger pro Computer haben und 
wäre recht nutzlos. Erst dadurch daß die Zieladresse eines UDP-Pakets 
eine Portnummer enthält, kann der IP-Netzwerkstack entscheiden, in 
welchen Socket er das Paket übergibt.

Als Analogie nehme man die Hausnummer in einer Postadresse. Ohne 
Hausnummer kommt die Postkarte zwar in die richtige Stadt und in die 
richtige Straße. Aber erst mit einer Hausnummer kann der Postbote 
entscheiden in welchen Briefkasten er sie stecken muß (in diesem 
vereinfachten Modell gibt es an jedem Haus nur einen Briefkasten).

von Rolf M. (rmagnus)


Lesenswert?

Nur am Rande:

brechbunkt schrieb:
> Anstatt nach erfolgter Verbindung einen neuen thread zu starten, der
> diesen bedient, möchte ich es bei nur einem einzigen belassen. Somit
> kann auch nur ein Client mit meinem Server gleichzeitig verbunden sein.

Du kannst auch in einem Thread beliebig viele Verbindungen haben. Mit 
select() oder poll() kannst du auf Daten von mehreren gleichzeitig 
warten. Damit kommt man ziemlich weit, ohne sich mit Threads rumschlagen 
zu müssen. Die braucht man eigentlich erst, wenn man soviel Last hat, 
dass man sie auf mehrere Prozessorkerne verteilen muss oder wenn das 
Generieren einer Nachricht so viel Zeit brauchen kann, dass andere 
Verbindungen dann sehr lange blockiert wären.

von Stefan F. (Gast)


Lesenswert?

Ja stimmt. Nur bestimtm die Anwendung selbst, auf welchen Ports sie 
lauschen möchte. Das Protokoll schreibt nicht vor, dass die Port Nummer 
einer Antwort mit der Portnummer einer Anfrage identisch sein muss.

von Axel S. (a-za-z0-9)


Lesenswert?

Rolf Magnus schrieb:
> brechbunkt schrieb:
>> Anstatt nach erfolgter Verbindung einen neuen thread zu starten, der
>> diesen bedient, möchte ich es bei nur einem einzigen belassen. Somit
>> kann auch nur ein Client mit meinem Server gleichzeitig verbunden sein.
>
> Du kannst auch in einem Thread beliebig viele Verbindungen haben. Mit
> select() oder poll() kannst du auf Daten von mehreren gleichzeitig
> warten.

Nur bringt das vergleichsweise wenig, wenn man einen UDP-Server baut. 
Denn der hat ja i.d.R. nur genau einen Socket. Im Gegensatz zu TCP, wo 
man den listen()ing Socket hat, auf dem man accept() macht, das dann für 
jede neue Verbindung einen neuen Socket ausspuckt.

Bei UDP hat man hingegen nur den einen Socket. Und aus dem kann man 
Pakete auch nur sequentiell auslesen. So lange das Programm regelmäßig 
zum revcfrom() kommt, ist alles in Butter. Darüber hinaus hat der 
IP-Stack ja auch noch eine Warteschlange (queue) für eingehende Pakete.

von (prx) A. K. (prx)


Lesenswert?

Axel Schwenke schrieb:
> Bei UDP hat man hingegen nur den einen Socket.

Nicht zwangsläufig. Man kann über diesen einen Socket einen separaten 
Port für die Kommunikation aushandeln. Dann geht auch mehr parallel.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.