Buch "Linux API. Comprehensive Guide »


Buch "Linux API. Comprehensive Guide »

Gudde Mëtteg Ech bréngen Iech d'Buch "Linux API. Comprehensive Guide "(Iwwersetzung vum Buch D'Linux Programméiere Interface). Et kann op der Websäit vum Verlag bestallt ginn, a wann Dir de Promo Code applizéiert LinuxAPI Dir kritt 30% Remise.

En Auszich aus dem Buch fir ze iwwerpréiwen:

Sockets: Server Architektur

An dësem Kapitel diskutéiere mir d'Grondlage vum Design vun iterativen a parallele Serveren, souwéi e speziellen inetd Daemon, deen d'Schafung vun Server-Säit Internet Uwendungen erliichtert.

Iteratioun a Parallel Serveren

Et ginn zwou gemeinsam Socket-baséiert Netzwierkserverarchitekturen:

  • iterativ: de Server servéiert Clienten ee gläichzäiteg, veraarbecht fir d'éischt d'Ufro (oder e puer Ufroe) vun engem Client an geet dann op den nächsten;

  • parallel: de Server ass entwéckelt fir verschidde Clienten zur selwechter Zäit ze déngen.

Sektioun 44.8 huet schonn e Beispill vun engem Iteratiounsserver baséiert op FIFO-Schlaangen.

Iteratiounsserver si meeschtens nëmme gëeegent a Situatiounen wou Client Ufroe relativ séier kënne veraarbecht ginn, well all Client muss waarden bis all aner Cliente virun him zerwéiert ginn. E gemeinsame Benotzungsfall fir dës Approche ass eenzel Ufroen an Äntwerten tëscht engem Client an engem Server auszetauschen.

Parallel Server si gëeegent a Fäll wou all Ufro e wesentleche Betrag vun Zäit brauch fir ze veraarbecht, oder de Client an de Server e laangen Austausch vu Messagen hunn. An dësem Kapitel konzentréieren mir haaptsächlech op déi traditionell (an einfachsten) Manéier parallel Serveren ze Design, déi ass eng separat Kand Prozess fir all neie Client ze schafen. Esou e Prozess mécht all d'Aarbecht vum Client ze servéieren, duerno ass et op en Enn. Zënter jidderee vun dëse Prozesser onofhängeg funktionnéiert, ass et méiglech verschidde Clienten zur selwechter Zäit ze déngen. D'Haaptaufgab vum Haaptserverprozess (Elteren) ass e separat Kand fir all neie Client ze kreéieren (alternativ, amplaz vu Prozesser, kënnt Dir Ausféierungsfäegkeeten erstellen).

An de folgende Sektioune kucke mir Beispiller vun iterativen a parallele Serveren op Basis vun Internet Domain Sockets. Dës zwee Server implementéieren eng vereinfacht Versioun vum Echo-Service (RFC 862), deen eng Kopie vun all Message, dee vum Client geschéckt gëtt.

Echo Iteration udp Server

An dësem an der nächster Sektioun wäerte mir Servere fir den Echo Service virstellen. Et ass verfügbar op Port Nummer 7 a funktionnéiert souwuel iwwer UDP wéi TCP (dësen Hafen ass reservéiert, an dofir muss den Echo Server mat Administrator Privilegien lafen).

Den Echo UDP Server liest dauernd Datagramme a bréngt eng Kopie vun hinnen un de Sender zréck. Well de Server nëmmen ee Message gläichzäiteg muss veraarbechten, geet hei duer mat enger iterativer Architektur. D'Headerdatei fir Server gëtt an der Oplëschtung 56.1-XNUMX gewisen.

Oplëschtung 56.1. Header Datei fir Programmer id_echo_sv.c an id_echo_cl.c

#include "inet_sockets.h" /* Deklaréiert eis Socketfunktiounen */
#include "tlpi_hdr.h"

#define SERVICE "echo" /* UDP Service Numm */

#define BUF_SIZE 500 /* Maximal Gréisst vun datagrams datt
ka vum Client a Server gelies ginn */
________________________________________________________________________ sockets/id_echo.h

Oplëschtung 56.2-XNUMX weist d'Serverimplementatioun. Et ass derwäert déi folgend Punkten ze notéieren:

  • fir de Server an den Daemon Modus ze setzen, benotze mir d'Funktioun becomeDaemon () aus Sektioun 37.2;

  • fir de Programm méi kompakt ze maachen, benotze mir d'Internet Domain Socket Bibliothéik entwéckelt an der Rubrik 55.12;

  • wann de Server kann net eng Äntwert op de Client zréck, et schreift e Message un d'Logbuch benotzt de syslog () Opruff.

An enger realer Applikatioun wäerte mir héchstwahrscheinlech eng gewësse Limit op d'Frequenz vun de Logbicher setzen mat Syslog (). Dëst géif d'Méiglechkeet eliminéieren datt en Ugräifer de Systemprotokoll iwwerschwemmt. Denkt och drun datt all Syslog () Uruff zimlech deier ass, well se als Standard fsync () benotzt.

Oplëschtung 56.2. En Iteratiounsserver deen den Echo UDP Service implementéiert

__________________________________________________sockets/id_echo_sv.c
# enthalen
#include "id_echo.h"
#include "become_daemon.h"

INT
main(int argc, char *argv[])
{
int sfd;
ssize_t numRead;
socklen_tlen;
struct sockaddr_storage claddr;
charbuf[BUF_SIZE];
char adrStr[IS_ADDR_STR_LEN];

wann (becomeDaemon(0) == -1)
errExit("becomeDaemon");

sfd = inetBind(SERVICE, SOCK_DGRAM, NULL);
wann (sfd == -1) {
syslog(LOG_ERR, "Konnt de Server Socket (%s) net erstellen",
Strerror (Feeler));
exit(EXIT_FAILURE);

/* Datagramme kréien a Kopien un d'Sender zréckginn */
}
fir(;;) {
len = sizeof(struct sockaddr_storage);
numRead = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

wann (numRead == -1)
errExit("recvfrom");
if (sendto(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!=nummerLiesen)
syslog(LOG_WARNING, "Feeler beim Echo vun der Äntwert op %s (%s)",
inetAddressStr((struct sockaddr *) &claddr, len,
adrStr, IS_ADDR_STR_LEN),
Strerror (Feeler));
}
}
__________________________________________________sockets/id_echo_sv.c

Mir benotzen de Programm an der Oplëschtung 56.3 fir de Server ze testen. Et benotzt och d'Internet Domain Socket Bibliothéik entwéckelt am Sektioun 55.12. De Client Programm hëlt den Numm vum Netzwierkhost wou de Server ass als éischt Argument op der Kommandozeil. De Client geet an eng Loop, wou se all eenzel vun de verbleiwen Argumenter op de Server als separat Datagramme schéckt, an dann d'Datagrammer, déi vum Server als Äntwert kritt goufen, liest an erausginn.

Oplëschtung 56.3. Client fir echo UDP Service

#include "id_echo.h"

INT
main(int argc, char *argv[])
{
int sfd,j;
size_tlen;
ssize_t numRead;
charbuf[BUF_SIZE];

wann (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s host msg...n", argv[0]);

/* Form d'Serveradress baséiert op dem éischte Kommandozeilargument */
sfd = inetConnect(argv[1], SERVICE, SOCK_DGRAM);
wann (sfd == -1)
fatal ("Konnt net mam Server Socket verbannen");

/* Schéckt de Rescht vun den Argumenter op de Server als separat Datagramme */
fir (j = 2; j < argc; j++) {
len = strlen(argv[j]);
wann (schreiwen(sfd, argv[j], len) != len)
fatal ("deelweis / gescheitert Schreiwen");

numRead = read(sfd, buf, BUF_SIZE);
wann (numRead == -1)
errExit("liesen");
printf("[%ld bytes] %.*sn", (laang) numRead, (int) numRead, buf);
}
exit(EXIT_SUCCESS);
}
__________________________________________________sockets/id_echo_cl.c

Déi folgend ass e Beispill vu wat mir wäerte gesinn wa mir de Server an zwee Client Instanzen starten:

$ su // Erfuerdert Privilegien fir un e reservéierten Hafen ze binden
Passwuert:
# ./id_echo_sv // De Server geet an den Hannergrond
# exit // Entlooss Administrator Rechter
$ ./id_echo_cl localhost Hallo Welt // Dëse Client schéckt zwee Datagramme
[5 Bytes] Hallo // De Client gëtt d'Äntwert vum Server aus
[5 Bytes] Welt
$ ./id_echo_cl localhost Äddi // Dëse Client schéckt een datagram
[7 Bytes] Äddi

Ech wënschen Iech eng agreabel Liesung)

Source: linux.org.ru