Linux IO-Multiplexing Epoll-Netzwerkprogrammierung

Linux IO-Multiplexing Epoll-Netzwerkprogrammierung

Vorwort

In diesem Kapitel werden grundlegende Linux-Funktionen und Epoll-Aufrufe verwendet, um ein vollständiges Server- und Client-Beispiel zu schreiben, das unter Linux ausgeführt werden kann. Die Funktionen des Clients und des Servers sind wie folgt:

  • Der Client liest eine Zeile aus der Standardeingabe und sendet sie an den Server
  • Der Server liest eine Zeile aus dem Netzwerk und gibt sie an den Client aus
  • Der Client empfängt die Antwort vom Server und gibt diese Zeile auf der Standardausgabe aus

Server

Der Code lautet wie folgt:

#include <unistd.h>
#include <sys/types.h> /* grundlegende Systemdatentypen */
#include <sys/socket.h> /* grundlegende Socket-Definitionen */
#include <netinet/in.h> /* sockaddr_in{} und andere Internetdefinitionen */
#include <arpa/inet.h> /* inet(3)-Funktionen */
#include <sys/epoll.h> /* epoll-Funktion */
#include <fcntl.h> /* nicht blockierend */
#include <sys/resource.h> /*setrlimit */
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define MAXEPOLLSIZE 10000
#define MAXLINE 10240
} // ...
int setnonblocking(int sockfd)
{
  wenn (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) {
    Rückgabe -1;
  }
  gebe 0 zurück;
}
int main(int argc, char **argv)
{
  int servPort = 6888;
  Int listenq = 1024;
  int listenfd, connfd, kdpfd, nfds, n, nread, curfds, acceptCount = 0;
  Struktur sockaddr_in servaddr, cliaddr;
  socklen_t socklen = Größe von (Struktur sockaddr_in);
  Struktur epoll_event ev;
  Struktur epoll_event Ereignisse[MAXEPOLLSIZE];
  Struktur rlimit rt;
  char-Puffer[MAXLINE];
  /* Legen Sie die maximale Anzahl an Dateien fest, die jeder Prozess öffnen darf */
  rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
  wenn (setrlimit(RLIMIT_NOFILE, &rt) == -1) 
  {
    perror("setrlimit-Fehler");
    Rückgabe -1;
  }
  bzero(&servaddr, Größe von(servaddr));
  servaddr.sin_family = AF_INET; 
  servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
  servaddr.sin_port = htons(servPort);
  listenfd = socket(AF_INET, SOCK_STREAM, 0); 
  wenn (listenfd == -1) {
    perror("Socket-Datei kann nicht erstellt werden");
    Rückgabe -1;
  }
  int opt ​​​​= 1;
  setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  wenn (nichtblockierendsetzen(listenfd) < 0) {
    perror("setnonblock-Fehler");
  }
  wenn (binden(listenfd, (Struktur sockaddr *) &servaddr, sizeof(Struktur sockaddr)) == -1) 
  {
    perror("Bindungsfehler");
    Rückgabe -1;
  } 
  wenn (hören(listenfd, listenq) == -1) 
  {
    perror("Abhörfehler");
    Rückgabe -1;
  }
  /* Erstellen Sie einen Epoll-Handle und fügen Sie den Listening-Socket zum Epoll-Set hinzu*/
  kdpfd = epoll_create(MAXEPOLLSIZE);
  ev.events = EPOLLIN | EPOLLET;
  ev.data.fd = listenfd;
  wenn (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) 
  {
    fprintf(stderr, "Fehler beim Einfügen des Epoll-Sets: fd=%d\n", listenfd);
    Rückgabe -1;
  }
  kurfds = 1;
  printf("epollserver-Start, Port %d, maximale Verbindung ist %d, Rückstand ist %d\n", servPort, MAXEPOLLSIZE, listenq);
  für (;;) {
    /* Auf das Eintreten eines Ereignisses warten */
    nfds = epoll_wait(kdpfd, Ereignisse, curfds, -1);
    wenn (nfds == -1)
    {
      perror("epoll_wait");
      weitermachen;
    }
    /* Alle Ereignisse verarbeiten */
    für (n = 0; n < nfds; ++n)
    {
      wenn (Ereignisse[n].data.fd == listenfd) 
      {
        connfd = akzeptieren(listenfd, (Struktur sockaddr *)&cliaddr,&socklen);
        wenn (connfd < 0) 
        {
          perror("Fehler akzeptieren");
          weitermachen;
        }
        sprintf(buf, "Formular %s akzeptieren:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
        printf("%d:%s", ++acceptCount, buf);

        wenn (curfds >= MAXEPOLLSIZE) {
          fprintf(stderr, "zu viele Verbindungen, mehr als %d\n", MAXEPOLLSIZE);
          schließen(connfd);
          weitermachen;
        } 
        wenn (nichtblockierendsetzen(connfd) < 0) {
          perror("setnonblocking-Fehler");
        }
        ev.events = EPOLLIN | EPOLLET;
        ev.data.fd = connfd;
        wenn (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0)
        {
          fprintf(stderr, "Hinzufügen von Socket '%d' zu epoll fehlgeschlagen: %s\n", connfd, strerror(errno));
          Rückgabe -1;
        }
        kurfds++;
        weitermachen;
      } 
      // Client-Anfrage verarbeiten if (handle(events[n].data.fd) < 0) {
        epoll_ctl(kdpfd, EPOLL_CTL_DEL, Ereignisse[n].data.fd,&ev);
        kurvt--;
      }
    }
  }
  schließen(listenfd);
  gebe 0 zurück;
}
int handle(int connfd) {
  int nicht lesen;
  char-Puffer[MAXLINE];
  nread = read(connfd, buf, MAXLINE); //Client-Socket-Stream lesen if (nread == 0) {
    printf("Client schließt die Verbindung\n");
    schließen(connfd);
    Rückgabe -1;
  } 
  wenn (Anzahl der Lesevorgänge < 0) {
    perror("Lesefehler");
    schließen(connfd);
    Rückgabe -1;
  }  
  write(connfd, buf, nread); //dem Client antworten return 0;
}

Kompilieren

Kompilieren und Starten des Servers

gcc epollserver.c -o epollserver
./epollserver

Zusammenfassen

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM. Wenn Sie mehr darüber erfahren möchten, schauen Sie sich bitte die folgenden Links an

Das könnte Sie auch interessieren:
  • Eine detaillierte Einführung in Linux IO
  • Tutorial zur Verwendung des iostat-Befehls unter Linux
  • Interessante Erklärung des Socket IO-Modells von Linux
  • Eine detaillierte Einführung in die fünf IO-Modelle unter Linux
  • Analyse des Linux-Hochleistungsnetzwerk-IO- und Reaktormodells

<<:  Welche Schleife ist in JavaScript die schnellste?

>>:  Anwendungsszenarien und Lösungen für die MySQL-Komprimierung

Artikel empfehlen

Detaillierte Erläuterung der logischen Architektur von MySQL

1. Gesamtarchitekturdiagramm Im Vergleich zu ande...

So verwalten Sie zwischengespeicherte Seiten in Vue

Inhaltsverzeichnis Problem 1: Zerstörung 1. Wie m...

Einführung in die Verwendung von Alt- und Titelattributen von HTML-Img-Tags

Wenn Browser-Anbieter die Standards umgehen und ei...

So verwenden Sie die Markdown-Editor-Komponente in Vue3

Inhaltsverzeichnis Installieren Komponenten impor...

Dieser Artikel zeigt Ihnen, wie Sie mit CSS-Kombinationsselektoren spielen

CSS-Kombinationsselektoren umfassen verschiedene ...

Vue realisiert problemlos Wasserzeicheneffekte

Vorwort: Verwenden Sie den Wasserzeicheneffekt im...

Sehen Sie sich den Befehl zum Ändern der MySQL-Tabellenstruktur an

Kurzbeschreibung Der Editor hat häufig Probleme m...

Beispielcode zur Installation von Jenkins mit Docker

Zwei Probleme, die bei der Installation von Docke...

Docker-Grundlagen

Vorwort: Docker ist eine Open-Source-Anwendungsco...

Detailliertes Beispiel für JavaScript-Array-Methoden

Inhaltsverzeichnis Einführung Erstellen eines Arr...

Tiefgreifendes Verständnis der verschiedenen Sperren von MySQL

Inhaltsverzeichnis Schlossübersicht Sperrklassifi...

CSS3-Übergang zum Erreichen des unterstrichenen Beispielcodes

In diesem Artikel wird der Beispielcode für den C...

Der Unterschied zwischen this.$router und this.$route in Vue und der push()-Methode

Im offiziellen Dokument heißt es: Durch Einfügen ...