Normalerweise wartet der Server an einer bekannten Adresse auf Service-Anforderungen. Der Server verhält sich solange inaktiv, bis ein Client eine Verbindungsanforderung an die Adresse des Servers schickt. Zu diesem Zeitpunkt "erwacht" der Server und bedient den Client, indem er die passenden Aktionen für die Anforderung des Clients ausführt. Auf den Server wird über die bekannte Internet-Adresse zugegriffen. Die Programmierung der Programm-Hauptschleife wird im folgenden Beispiel gezeigt.
Im Beispielprogramm benutzt der Server die folgenden Funktionen der Socket- bzw. POSIX-Schnittstelle:
socket(): Socket erzeugen
bind(): einem Socket einen Namen zuordnen
listen(): einen Socket auf Verbindungsanforderungen „abhören“
accept(): eine Verbindung auf einem Socket annehmen
recv(): Daten von einem Socket lesen
close(): Socket schließen
Beispiel: Verbindungsorientierter Server
#include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define TESTPORT 2222 #define ERROR_EXIT(M) perror(M); exit(1) int main(int argc, char **argv) { int sock, length; struct sockaddr_in server; int msgsock; char buf[1024]; int rval; /* Socket erzeugen */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ERROR_EXIT("Create stream socket"); } /* Dem Socket einen Namen zuordnen */ server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(TESTPORT); if (bind(sock, (struct sockaddr *)&server, sizeof (server) ) < 0) { ERROR_EXIT("Bind stream socket"); } /* Beginn mit der Annahme von Verbindungsanforderungen */ listen(sock, 5); if ((msgsock = accept(sock, (struct sockaddr *)0, NULL)) < 0) { ERROR_EXIT("Accept connection"); } else do { memset(buf, 0, sizeof buf); if ((rval = recv(msgsock, buf, 1024, 0)) < 0) { ERROR_EXIT("Reading stream message"); } else if (rval == 0) { fprintf(stderr, "Ending connection\n"); } else { fprintf(stdout, "->%s\n",buf); } } while (rval != 0); close(msgsock); close(sock); return 0; }
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. Über diese Portnummer kann er im Netz adressiert werden.
Mit der Funktion listen() legt der Server fest, dass der Socket Verbindungsanforderungen annehmen kann. Verbindungsanforderungen nimmt der Server mit accept() an. Der Return-Wert von accept() wird überprüft, um sicherzustellen, dass die Verbindung erfolgreich aufgebaut wurde. Sobald die Verbindung aufgebaut ist, werden die Daten mit der Funktion recv() vom Socket gelesen. Mit der Funktion close() schließt der Server den Socket.
Das Beispielprogramm ist nur für die Kommunikationsdomäne AF_INET gültig. Wenn es gemäß den Angaben in "Socket- Adressierung" und "Socket erzeugen" geändert wird, gilt es auch für die Domäne AF_INET6.