Raamat "Linux API. Põhjalik juhend»


Raamat "Linux API. Põhjalik juhend»

Tere päevast Juhin teie tähelepanu raamatule “Linux API. Põhjalik juhend "(raamatu tõlge Linuxi programmeerimisliides). Seda saab tellida väljaandja veebisaidilt ja kui rakendate sooduskoodi LinuxAPI saad 30% allahindlust.

Katkend raamatust arvustamiseks:

Pistikupesad: serveri arhitektuur

Selles peatükis käsitleme iteratiivsete ja paralleelsete serverite kujundamise põhitõdesid, samuti spetsiaalset inetd-deemonit, mis hõlbustab serveripoolsete Interneti-rakenduste loomist.

Iteratsioon ja paralleelserverid

Levinud on kaks soklipõhist võrguserveri arhitektuuri:

  • iteratiivne: server teenindab kliente ükshaaval, esmalt töötleb ühe kliendi päringut (või mitut päringut) ja liigub seejärel järgmise juurde;

  • paralleelselt: server on loodud teenindama mitut klienti korraga.

Jaotis 44.8 on juba esitanud FIFO järjekordadel põhineva iteratsiooniserveri näite.

Iteratsiooniserverid sobivad tavaliselt vaid olukordades, kus klientide päringuid saab üsna kiiresti töödelda, kuna iga klient peab ootama, kuni kõik teised tema ees olevad kliendid on teenindatud. Selle lähenemisviisi tavaline kasutusjuht on üksikute päringute ja vastuste vahetamine kliendi ja serveri vahel.

Paralleelserverid sobivad juhtudel, kui iga päringu töötlemine võtab palju aega või kliendi ja serveri vahel on pikk sõnumivahetus. Selles peatükis keskendume peamiselt traditsioonilisele (ja lihtsaimale) paralleelserverite kujundamise võimalusele, milleks on iga uue kliendi jaoks eraldi alamprotsessi loomine. Selline protsess teeb ära kogu kliendi teenindamise töö, misjärel see lõpeb. Kuna kõik need protsessid toimivad iseseisvalt, on võimalik teenindada mitut klienti korraga. Põhiserveri protsessi (vanema) põhiülesanne on luua igale uuele kliendile eraldi alam (alternatiivina saate protsesside asemel luua täitmislõime).

Järgmistes osades vaatleme näiteid iteratiivsetest ja paralleelsetest serveritest, mis põhinevad Interneti-domeeni pesadel. Need kaks serverit rakendavad kajateenuse (RFC 862) lihtsustatud versiooni, mis tagastab kliendi saadetud sõnumite koopia.

kaja iteratsiooni udp server

Selles ja järgmises jaotises tutvustame kajateenuse servereid. See on saadaval pordil number 7 ja töötab nii UDP kui ka TCP kaudu (see port on reserveeritud ja seetõttu tuleb kajaserverit käivitada administraatori õigustega).

Echo UDP server loeb pidevalt datagramme ja saadab nende koopia saatjale tagasi. Kuna server peab korraga töötlema ainult ühte sõnumit, piisab siin iteratiivsest arhitektuurist. Serverite päisefail on näidatud loendis 56.1-XNUMX.

Nimekiri 56.1. Programmide id_echo_sv.c ja id_echo_cl.c päisefail

#include "inet_sockets.h" /* Deklareerib meie pesafunktsioonid */
#include "tlpi_hdr.h"

#define SERVICE "echo" /* UDP teenuse nimi */

#define BUF_SIZE 500 /* Datagrammide maksimaalne suurus, mis
saavad lugeda klient ja server */
______________________________________________________________________________ pistikupesad/id_echo.h

Nimekiri 56.2-XNUMX näitab serveri rakendamist. Tasub pöörata tähelepanu järgmistele punktidele:

  • serveri deemoni režiimi panemiseks kasutame jaotisest 37.2 pärit funktsiooni makesDaemon();

  • programmi kompaktsemaks muutmiseks kasutame jaotises 55.12 välja töötatud interneti domeeni sokliteegi;

  • kui server ei saa kliendile vastust tagastada, kirjutab ta logisse sõnumi, kasutades väljakutset syslog().

Reaalses rakenduses kehtestaksime suure tõenäosusega teatud piirangu sõnumite logimise sagedusele, kasutades funktsiooni syslog(). See välistaks võimaluse, et ründaja ajab süsteemilogi üle. Samuti pidage meeles, et iga syslog() kõne on üsna kallis, kuna see kasutab vaikimisi funktsiooni fsync().

Nimekiri 56.2. Iteratsiooniserver, mis rakendab echo UDP teenust

____________________________________________________________________________sockets/id_echo_sv.c
#kaasa
#include "id_echo.h"
#include "become_daemon.h"

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

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

sfd = inetBind(SERVICE, SOCK_DGRAM, NULL);
if (sfd == -1) {
syslog(LOG_ERR, "Ei saanud luua serveri soklit (%s)",
strerror(errno));
exit(EXIT_FAILURE);

/* Andmegrammide vastuvõtmine ja koopiate tagastamine saatjatele */
}
jaoks(;;) {
len = suurus(struct sockaddr_storage);
numRead = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

if (arvRead == -1)
errExit("recvfrom");
if (sendto(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!=NumRead)
syslog(LOG_WARNING, "Viga vastuse kajamisel aadressile %s (%s)",
inetAddressStr((struct sockaddr *) &claddr, len,
addrStr, IS_ADDR_STR_LEN),
strerror(errno));
}
}
____________________________________________________________________________sockets/id_echo_sv.c

Serveri testimiseks kasutame programmi loendis 56.3. Samuti kasutab see jaotises 55.12 välja töötatud Interneti-domeeni sokliteeki. Klientprogramm võtab käsureal esimese argumendina selle võrguhosti nime, kus server asub. Klient siseneb tsüklisse, kus ta saadab kõik ülejäänud argumendid serverisse eraldi datagrammidena ning seejärel loeb ja väljastab vastuseks serverilt saadud datagrammid.

Nimekiri 56.3. Echo UDP teenuse klient

#include "id_echo.h"

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

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

/* Moodustage serveri aadress esimese käsurea argumendi põhjal */
sfd = inetConnect(argv[1], TEENUS, SOCK_DGRAM);
if (sfd == -1)
fatal("Ei saanud ühendust serveri pesaga");

/* Saada ülejäänud argumendid serverisse eraldi datagrammidena */
jaoks (j = 2; j < argc; j++) {
len = strlen(argv[j]);
if (write(sfd, argv[j], len) != len)
fataalne ("osaline/ebaõnnestunud kirjutamine");

numRead = loe(sfd, buf, BUF_SIZE);
if (arvRead == -1)
errExit("loe");
printf("[%ld baiti] %.*sn", (pikk) numRead, (int) numRead, buf);
}
exit(EXIT_SUCCESS);
}
_______________________________________________________________________pesad/id_echo_cl.c

Järgmine on näide sellest, mida näeme serveri ja kahe kliendi eksemplari käivitamisel:

$ su // Nõuab õigusi reserveeritud pordiga sidumiseks
Salasõna:
# ./id_echo_sv // Server läheb taustale
# exit // Loobuge administraatori õigustest
$ ./id_echo_cl localhost hello world // See klient saadab kaks datagrammi
[5 baiti] tere // Klient väljastab serverilt saadud vastuse
[5 baiti] maailm
$ ./id_echo_cl localhost hüvasti // See klient saadab ühe datagrammi
[7 baiti] hüvasti

Soovin teile meeldivat lugemist)

Allikas: linux.org.ru