In den meisten Fällen arbeiten Server verbindungsorientiert. Einige Services basieren jedoch auf der Verwendung von Datagramm-Sockets und arbeiten somit verbindungslos.
In den Programmbeispielen verwendet der Server die folgenden Funktionen der Socket-Schnittstelle:
socket(): Socket erzeugen
bind(): einem Socket einen Namen zuordnen
recvfrom(): Nachricht von einem Socket lesen
soc_close(): Socket schließen
Das Programm wird in zwei Varianten vorgestellt:
In der ersten Variante (Beispiele 1 und 3) wird das Programm beendet, wenn eine Nachricht ankommt (read()).
In der zweiten Variante (Beispiele 2 und 4) wartet das Programm in einer Endlosschleife auf weitere Nachrichten, nachdem eine Nachricht gelesen wurde.
Beispiel 1: Verbindungsloser Server ohne Programmschleife für AF_INET
#include <stdio.h> #include <sys.types.h> #include <sys.socket.h> #include <ioctl.h> #include <signal.h> #include <netinet.in.h> #include <netdb.h> #define TESTPORT 2222 /* * Dieses Programm erzeugt einen Datagramm-Socket, ordnet ihm einen * definierten Port zu und liest dann Daten vom Socket. */ main() { int sock; int length; struct sockaddr_in server; char buf[1024]; /* Erzeugen des Sockets, von dem gelesen werden soll. */ sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0 ) { perror("Socket datagram"); exit(1); } /* Dem Server "server" unter Verwendung von Wildcards einen * Namen zuordnen */ server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(TESTPORT); if (bind(sock, &server, sizeof server ) < 0) { perror("Bind datagram socket"); exit(1); } /* Beginn des Lesens vom Server */ length = sizeof(server); memset(buf,0,sizeof(buf)); if ( recvfrom(sock, buf, 1024,0, &server, &length) < 0 ) { perror("recvfrom"); exit(1); } else printf("->%s\n",buf); soc_close(sock); }
Beispiel 2: Verbindungsloser Server mit Programmschleife für AF_INET
#include <sys.types.h> #include <sys.socket.h> #include <ioctl.h> #include <signal.h> #include <netinet.in.h> #include <netdb.h> #include <stdio.h> #define TESTPORT 2222 /* Dieses Programm erzeugt einen Datagramm-Socket, ordnet ihm einen * definierten Port zu und liest dann Daten vom Socket. */ main() { int sock; int length; struct sockaddr_in server; char buf[1024]; /* Erzeugen des Sockets, von dem gelesen werden soll. */ sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0 ) { perror("Socket datagram"); exit(1); } /* Dem Server "server" unter Verwendung von Wildcards einen * Namen zuordnen */ server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(TESTPORT); if (bind(sock, &server, sizeof server ) < 0) { perror("Bind datagram socket"); exit(1); } /* Beginn des Lesens vom Server */ length = sizeof(server); for (;;) { memset(buf,0,sizeof(buf)); if ( recvfrom(sock, buf, sizeof(buf),0, &server, &length) < 0 ) { perror("recvfrom"); exit(1); } else printf("->%s\n",buf); } /* Da dieses Programm in einer Endlos-Schleife läuft, wird der * Socket "sock" niemals explizit geschlossen. Allerdings werden alle * Sockets automatisch geschlossen, wenn der Prozess abgebrochen wird. */ }
Beispiel 3: Verbindungsloser Server ohne Programmschleife für AF_INET6
#include <stdio.h> #include <sys.types.h> #include <sys.socket.h> #include <ioctl.h> #include <signal.h> #include <netinet.in.h> #include <netdb.h> #define TESTPORT 2222 /* * Dieses Programm erzeugt einen Datagramm-Socket, ordnet ihm einen * definierten Port zu und liest dann Daten vom Socket. */ main() { int sock; int length; struct sockaddr_in6 server; struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; char buf[1024]; /* Erzeugen des Sockets, von dem gelesen werden soll. */ sock = socket(AF_INET6, SOCK_DGRAM, 0); if (sock < 0 ) { perror("Socket datagram"); exit(1); } /* Dem Server "server" unter Verwendung von Wildcards einen Namen zuordnen */ server.sin6_family = AF_INET6; memcpy(server.sin6_addr.s6_addr, in6addr_any.s6_addr, 16) ; server.sin6_port = htons(TESTPORT); if (bind(sock, &server, sizeof server ) < 0) { perror("Bind datagram socket"); exit(1); } /* Beginn des Lesens vom Server */ length = sizeof(server); memset(buf,0,sizeof(buf)); if ( recvfrom(sock, buf, 1024,0, &server, &length) < 0 ) { perror("recvfrom"); exit(1); } else printf("->%s\n",buf); soc_close(sock); }
Beispiel 4: Verbindungsloser Server mit Programmschleife für AF_INET6
#include <sys.types.h> #include <sys.socket.h> #include <ioctl.h> #include <signal.h> #include <netinet.in.h> #include <netdb.h> #include <stdio.h> #define TESTPORT 2222 /* Dieses Programm erzeugt einen Datagramm-Socket, ordnet ihm einen * definierten Port zu und liest dann Daten vom Socket. */ main() { int sock; int length; struct sockaddr_in6 server; struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; char buf[1024]; /* Erzeugen des Sockets, von dem gelesen werden soll. */ sock = socket(AF_INET6, SOCK_DGRAM, 0); if (sock < 0 ) { perror("Socket datagram"); exit(1); } /* Dem Server "server" unter Verwendung von Wildcards einen * Namen zuordnen */ server.sin6_family = AF_INET6; memcpy(server.sin6_addr.s6_addr ,in6addr_any.s6_addr,16); server.sin6_port = htons(TESTPORT); if (bind(sock, &server, sizeof server ) < 0) { perror("Bind datagram socket"); exit(1); } /* Beginn des Lesens vom Server */ length = sizeof(server); for (;;) { memset(buf,0,sizeof(buf)); if ( recvfrom(sock, buf, sizeof(buf),0, &server, &length) < 0 ) { perror("recvfrom"); exit(1); else printf("->%s\n",buf); } /* Da dieses Programm in einer Endlos-Schleife läuft, wird der * Socket "sock" niemals explizit geschlossen. Allerdings werden alle * Sockets automatisch geschlossen, wenn der Prozess abgebrochen wird. */ }
In den Programmbeispielen zu AF_INET und AF_INET6 werden folgende Arbeitsschritte durchgeführt:
- Der Server erzeugt mit der Funktion socket() einen Kommunikationsendpunkt (Socket) und den zugehörigen Deskriptor.
Mit der Funktion bind() wird dem Server-Socket eine definierte Portnummer zugeordnet, sodass er über diese Portnummer vom Netz aus adressiert werden kann.
Von einem Socket des Typs SOCK_DGRAM kann mit der Funktion recvfrom() gelesen werden.
Als Ergebnis wird die Länge der gelesenen Nachricht geliefert. Wenn keine Nachricht vorhanden ist, wird der Prozess blockiert, bis eine Nachricht eintrifft.