UDP-Client mit bind()

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

UDP-Client mit bind()

Beitrag von Columbus » 16.04.2008 14:44:20

Was mir schon seit langem auf der Seele brante, oder was ich nie zu fragen wagt:
in dem Buch "Linux-Unix-Programmierung" von Jürgen Wolf im Galileo-Verlag wird ein UDP-Client gezeigt, bei dem die Socket-Adresse mit bind an die IP-Struktur "gebunden" wird.
Ausserdem wird die UDP-Socket folgendermaßen erzeugt

Code: Alles auswählen

s = socket (AF_INET, SOCK_DGRAM, 0);
die ersten beiden Parameter sind iO aber der letzte '0'. Hier habe ich verschiedene Informationen. Ich kenne es hauptsächlich als Feld um das Protokoll einzugeben.
Im obrigen Beispiel verwende ich Datagramme, also muss ich als Protokoll IPPROTO_UDP eintragen. Wäre es SOCK_STREAM müsste ich IPPROTO_TCP eintragen. In der M$-Dokumentation von Windows-Sockets bedeutet eine 0 hier "unspezifiziert". Hmmmm

Aber was mich wirklich eher wundert ist daß ein Client-UDP-Socket mit bind aufgerufen wird. Macht das Sinn?

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: UDP-Client mit bind()

Beitrag von gms » 16.04.2008 16:16:03

Columbus hat geschrieben:Wäre es SOCK_STREAM müsste ich IPPROTO_TCP eintragen. In der M$-Dokumentation von Windows-Sockets bedeutet eine 0 hier "unspezifiziert".
"unspezifiziert" bedeutet, daß das Default-Protokoll für den gewählten Typ genommen wird.
Columbus hat geschrieben: Aber was mich wirklich eher wundert ist daß ein Client-UDP-Socket mit bind aufgerufen wird. Macht das Sinn?
mit "bind" wird dem Socket eine Adresse ( Port ) zugeordnet. Das macht natürlich Sinn solange der Socket nicht gebunden ist und du z.B einen vorgegebenen Port benutzen möchtest oder den Port schon vor einem "connect" festlegen möchtest

Gruß
gms

edit:
Columbus hat geschrieben:Wäre es SOCK_STREAM müsste ich IPPROTO_TCP eintragen.
mußt du auch hier nicht:

Code: Alles auswählen

gms1 ~ # cat x.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>

int main() {
  int sock=socket(PF_INET,SOCK_STREAM,0);
  if ( sock == -1 ) {
    perror("socket");
    exit(1);
  }
  printf("socket=%d\n",sock);
  close(sock);
  return 0;
}
gms1 ~ # gcc -o x x.c && ./x
socket=3

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Re: UDP-Client mit bind()

Beitrag von Columbus » 16.04.2008 17:08:02

gms hat geschrieben: mit "bind" wird dem Socket eine Adresse ( Port ) zugeordnet. Das macht natürlich Sinn solange der Socket nicht gebunden ist und du z.B einen vorgegebenen Port benutzen möchtest oder den Port schon vor einem "connect" festlegen möchtest
Aber das ist es ja gerade. Für eine UDP-Verbindung als Client brauche ich ja kein Connct. Einfach nur den Socket erzeugen und dann sento?!?!
Besonders schlecht ist sowas, wenn der UDP-Server auf dem gleichen Rechner sitzt und diesen Port schon "gebunden" hat.

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: UDP-Client mit bind()

Beitrag von gms » 16.04.2008 17:27:32

Columbus hat geschrieben: Besonders schlecht ist sowas, wenn der UDP-Server auf dem gleichen Rechner sitzt und diesen Port schon "gebunden" hat.
einen Socket auf eine schon belegte Adresse binden zu wollen führt zu einem Fehler, was aber nicht "besonders schlecht" ist, sondern sogar besonders gut ist :wink:
Hat aber auch keiner gesagt, daß du sowas machen sollst :wink:
Columbus hat geschrieben: Aber das ist es ja gerade. Für eine UDP-Verbindung als Client brauche ich ja kein Connct. Einfach nur den Socket erzeugen und dann sento?!?!
Ich habe jetzt wirklich ein Problem dir zu folgen! Auch hier hat keiner gesagt, daß du ein "connect" benötigst! Wenn du aber über UDP mit einer anderen Adresse 1:1 kommunizieren möchtest, KANNST du "connect" verwenden

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Re: UDP-Client mit bind()

Beitrag von Columbus » 24.04.2008 12:43:28

Sorry, daß ich erst jetzt antworte. Jetzt fällt es mir schwer in diesen Kontext wieder reinzufinden.
Also es ging bei mir nicht um ein Konkretes Problem. Ich bin nur dabei einen UDP-Client und UDP-Server zu schreiben. Dabei mache ich das folgendermaßen:
Client:
1.) Erzeuge Socket mit socket
2.) Erzeuge sockaddr Struktur mit der Adresse und Port des Servers
3.) Verändere die Socket-Eigenschaften mit setsockopt
4.) Schicke Datenpackete mit sendto an den Server.
Letztes passiert ohne connect. Connect dachte ich wäre Eigenart von TCP!?!?

Server:
1.) Erzeuge Socket mit socket
2.) Erzeuge sockaddr Struktur mit der Adresse und Port des Servers
3.) Verändere die Socket-Eigenschaften mit setsockopt
4.) Verbinde die sockaddr-Struktur mit dem Socket
5.) Warte in einer Endlosschleife auf ankommende Packete (mit recvfrom)
Letztes passiert ohne Listen und/oder Accept. Das ist für mich auch für TCP-Verbindungen "verbunden"??!?

Nun habe ich in verschiedenen Beispielen im Netz (u.a. in dem OpenBook von J.Wolf "C von A bis Z") daß auch bei UDP-Clients "gebunden" wird.
Ich habe mich einfach nur gewundert daß so auch möglich ist und dachte hier wäre eine Lösung für mein eigentliches Problem.

Die erste Hürde lag ja schon darin, daß ich den Server und Client auf meinem kleinen Notebook mit SingleProzessor (Athlon/Geode) habe laufen lassen(zum Testen). Einmal dadurch daß der Server den Port schon gebunden hat, also UDP-Port 4242 z.B. und ein weiterer Prozess versucht auch darauf zuzugreifen.
Und es gibt ein Problem mit dem Singlecore-Prozessor wenn zwei Prozesse sich über UDP unterhalten. Denn ohne Flusskontrolle schreibt der Client einfach etwas raus, während der Server gar keine Chance hat etwas entgegen zu nehmen, weil er ja nicht den Prozessor hat. Also geht bei diesem Test zwangsläufig was verloren, aber es ist ja nur ein Test.

Mein eigentliche Aufgabe ist zwei WinXP® Rechner (ja ich weis, hier eigentlich OT, aber ich muss es nun mal machen) über eine Gigabit-Ethernet-Leitung und UDP zu verbinden. Zur Zeit sind damit aber nur 200MBit drin, mit
TCP komme ich immerhin auf knapp 600MBit. Drum schraub ich mit setsockopt am UDP-Cache.

Ich habe hier ins Forum gepostet, weil ich mich schlicht einfach gewundert habe, daß in einigen Beispielen eben UDP-Verbindungen Clientseitig mit Bind aufgebaut werden.

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: UDP-Client mit bind()

Beitrag von gms » 27.04.2008 22:33:29

Columbus hat geschrieben: Ich habe hier ins Forum gepostet, weil ich mich schlicht einfach gewundert habe, daß in einigen Beispielen eben UDP-Verbindungen Clientseitig mit Bind aufgebaut werden.
aus der Sicht des UDP Protokolls gibt es keinen Client und keinen Server, daher kann jeder Datagram-Socket auch zu jeder Zeit senden und empfangen. Das ist ja auch der Vorteil von UDP, daß die Flußkontrolle an die Bedürfnisse der Applikation angepaßt werden kann, oder eben ganz darauf verzichtet werden kann, wenn kein Bedarf dafür besteht.
Columbus hat geschrieben: Nun habe ich in verschiedenen Beispielen im Netz (u.a. in dem OpenBook von J.Wolf "C von A bis Z") daß auch bei UDP-Clients "gebunden" wird.
wie gesagt, der sogenannte "Client" kann auf diesem Datagram-Socket auch unaufgefordert Daten empfangen, daher gibt es aus der Sicht des UDP-Protokoll keinen Server und keinen Client.
Schau dir z.B einmal einen DNS Server an, der auf dem gleichen Port die Anfragen seiner Clients bekommt, mit dem er auch die Anfragen an den übergeordneten Server schickt. Hier ist also "serverseitig" gleich "clientseitig".
Je nach Bedarf kann es also auch für einen Client sinnvoll sein, den Datagram Socket zu binden, entweder weil er einen speziellen Port verwenden möchte, oder weil er nur ein spezielles Interface verwenden möchte.
Columbus hat geschrieben: Mein eigentliche Aufgabe ist zwei WinXP® Rechner (ja ich weis, hier eigentlich OT, aber ich muss es nun mal machen) über eine Gigabit-Ethernet-Leitung und UDP zu verbinden. Zur Zeit sind damit aber nur 200MBit drin, mit TCP komme ich immerhin auf knapp 600MBit.
TCP mit seiner starren Flußkontrolle sollte eigentlich das untere Limit sein.
Columbus hat geschrieben:Und es gibt ein Problem mit dem Singlecore-Prozessor wenn zwei Prozesse sich über UDP unterhalten. Denn ohne Flusskontrolle schreibt der Client einfach etwas raus, während der Server gar keine Chance hat etwas entgegen zu nehmen, weil er ja nicht den Prozessor hat. Also geht bei diesem Test zwangsläufig was verloren, aber es ist ja nur ein Test.
das ist eigentlich kein Sonderfall, auch bei einem "Remote-Server" ist nie gewährleistet, daß dieser gerade einen Prozessor hat.

Gruß
gms

Antworten