Die Programmierung der Programm-Hauptschleife wird in den folgenden Beispielen gezeigt.
In den Beispielprogrammen benutzt der Server die folgenden Funktionen der Socket-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
soc_close(): Socket schließen
Beispiel: Verbindungsorientierter Server bei AF_INET
#include <stdio.h> #include <sys.types.h> #include <sys.socket.h> #include <netinet.in.h> #include <netdb.h> main(argc, argv) int argc; char *argv[]; { #define TESTPORT 2222 int sock, length; struct sockaddr_in server; struct sockaddr_in client; int clientlen; int msgsock; char buf[1024]; int rval; memset(&server,'\0',sizeof(server)); memset(&client,'\0',sizeof(client)); clientlen = sizeof(client); /* Socket erzeugen */ sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("Create stream socket"); exit(1); } /* 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) { perror("Bind stream socket"); exit(1); } /* Beginn mit der Annahme von Verbindungsanforderungen */ listen(sock, 5); msgsock = accept(sock, (struct sockaddr *)&client, &clientlen); if (msgsock == -1) { perror("Accept connection"); exit(1); } else do { memset(buf, 0, sizeof buf); if ((rval = recv(msgsock, buf, 1024, 0)) < 0) { perror("Reading stream message"); exit(1); } else if (rval == 0 ) fprintf(stderr, "Ending connection\n"); else fprintf(stdout, "->%s\n", buf); } while (rval != 0); soc_close(msgsock); soc_close(sock); }
Beispiel: Verbindungsorientierter Server bei AF_INET6
#include <stdio.h> #include <sys.types.h> #include <sys.socket.h> #include <netinet.in.h> #include <netdb.h> main(argc, argv) int argc; char *argv[]; { #define TESTPORT 2222 int sock, length; struct sockaddr_in6 server; struct sockaddr_in6 client; int clientlen; struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; int msgsock; char buf[1024]; int rval; memset(&server,'\0',sizeof(server)); memset(&client,'\0',sizeof(client)); clientlen = sizeof(client); /* Socket erzeugen */ sock = socket(AF_INET6, SOCK_STREAM, 0); if (sock < 0) { perror("Create stream socket"); exit(1); } /* Dem Socket 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, (struct sockaddr *)&server, sizeof (server) ) < 0) { perror("Bind stream socket"); exit(1); } /* Beginn mit der Annahme von Verbindungsanforderungen */ listen(sock, 5); msgsock = accept(sock, (struct sockaddr *)&client, &clientlen); if (msgsock == -1) { perror("Accept connection"); exit(1); } else do { memset(buf, 0, sizeof buf); if ((rval = recv(msgsock, buf, 1024, 0)) < 0) { perror("Reading stream message"); exit(1); } else if (rval == 0 ) fprintf(stderr, "Ending connection\n"); else fprintf(stdout, "->%s\n", buf); } while (rval != 0); soc_close(msgsock); soc_close(sock); }
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. Über diese Portnummer kann er im Netz adressiert werden.
Mit der Funktion listen() stellt der Server fest, ob Verbindungsanforderungen anstehen.
Verbindungsanforderungen kann der Server mit accept() annehmen. Der Returnwert 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 soc_close() schließt der Server den Socket.