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.