Unix Socket - Server Beispiele
Um einen Prozess zu einem TCP-Server zu machen, müssen Sie die folgenden Schritte ausführen:
Erstellen Sie einen Socket mit dem Systemaufruf socket () .
Binden Sie den Socket mithilfe des Systemaufrufs bind () an eine Adresse . Bei einem Server-Socket im Internet besteht eine Adresse aus einer Portnummer auf dem Host-Computer.
Achten Sie auf Verbindungen mit dem Systemaufruf listen () .
Akzeptieren Sie eine Verbindung mit dem Systemaufruf accept () . Dieser Aufruf wird normalerweise blockiert, bis ein Client eine Verbindung zum Server herstellt.
Senden und Empfangen von Daten mithilfe der Systemaufrufe read () und write () .
Lassen Sie uns diese Schritte nun in Form von Quellcode ausführen. Fügen Sie diesen Code in die Datei server.c ein und kompilieren Sie ihn mit dem gcc- Compiler.
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here process will
* go in sleep mode and will wait for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
/* Accept actual connection from the client */
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* If connection is established then start communicating */
bzero(buffer,256);
n = read( newsockfd,buffer,255 );
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",buffer);
/* Write a response to the client */
n = write(newsockfd,"I got your message",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
return 0;
}
Mehrere Verbindungen verarbeiten
Damit der Server mehrere Verbindungen gleichzeitig verarbeiten kann, nehmen wir im obigen Code die folgenden Änderungen vor:
Setzen Sie die accept- Anweisung und den folgenden Code in eine Endlosschleife.
Rufen Sie nach dem Herstellen einer Verbindung fork () auf, um einen neuen Prozess zu erstellen.
Der untergeordnete Prozess schließt sockfd und ruft die Doprocessing- Funktion auf, wobei der neue Socket-Dateideskriptor als Argument übergeben wird. Wenn die beiden Prozesse ihre Konversation abgeschlossen haben, wie durch die Rückgabe von doprocessing () angezeigt , wird dieser Prozess einfach beendet.
Der übergeordnete Prozess schließt newsockfd . Da sich der gesamte Code in einer Endlosschleife befindet, kehrt er zur accept-Anweisung zurück, um auf die nächste Verbindung zu warten.
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
Die folgende Codesequenz zeigt eine einfache Implementierung der Doprocessing- Funktion.
void doprocessing (int sock) {
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",buffer);
n = write(sock,"I got your message",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}