U libru di l'API Linux. Guida cumpleta »


U libru di l'API Linux. Guida cumpleta »

Bonghjornu Aghju purtatu à a vostra attenzione u libru "Linux API. Guida cumpleta "(traduzzione di u libru L'interfaccia di prugrammazione Linux). Pò esse urdinatu nantu à u situ web di l'editore, è se applica u codice promo LinuxAPI riceverete un scontu di 30%.

Un estrattu di u libru per a rivista:

Sockets: architettura di u servitore

In questu capitulu, discuteremu i principii di cuncepimentu di servitori iterativi è paralleli, è ancu un daemon speciale inetd chì facilita a creazione di applicazioni Internet di u servitore.

Iterazione è Server Paralleli

Ci sò duie architetture cumuni di servitori di rete basati in socket:

  • iterativu : u servitore serve à i clienti unu à u tempu, prima trasfurmendu a dumanda (o parechje dumande) di un cliente è dopu passà à u prossimu;

  • parallel: u servitore hè pensatu per serve parechji clienti à u stessu tempu.

A sezione 44.8 hà digià furnitu un esempiu di un servitore di iterazione basatu nantu à file FIFO.

I servitori di iterazione sò generalmente adattati solu in situazioni induve e richieste di i clienti ponu esse trattate abbastanza rapidamente, postu chì ogni cliente deve aspittà finu à chì qualsiasi altri clienti davanti sò stati serviti. Un casu d'usu cumuni per questu approcciu hè di scambià richieste è risposti unichi trà un cliente è un servitore.

I servitori paralleli sò adattati in i casi induve ogni dumanda piglia una quantità significativa di tempu per processà, o u cliente è u servitore anu un longu scambiu di missaghji. In questu capitulu, avemu principarmenti focu annantu à u modu tradiziunale (è più faciule) di cuncepisce servitori paralleli, chì hè di creà un prucessu di zitellu separatu per ogni novu cliente. Un tali prucessu faci tuttu u travagliu di serve u cliente, dopu chì finisce. Siccomu ognuna di sti prucessi opera indipindentamente, hè pussibule serve parechji clienti à u stessu tempu. U compitu principalu di u prucessu di u servitore principale (parent) hè di creà un zitellu separatu per ogni novu cliente (in alternativa, invece di prucessi, pudete creà fili di esecuzione).

In e sezzioni seguenti, fighjeremu esempi di servitori iterativi è paralleli basati in sockets di domini internet. Questi dui servitori implementanu una versione simplificata di u serviziu di eco (RFC 862) chì torna una copia di ogni messagiu mandatu da u cliente.

echo iterazione udp server

In questa è a prossima seccione, introduceremu i servitori per u serviziu di eco. Hè dispunibule nantu à u portu numeru 7 è travaglia sia nantu à UDP è TCP (stu portu hè riservatu, è per quessa u servitore di eco deve esse eseguitu cù privilegi di amministratore).

U servitore Echo UDP leghje constantemente datagrammi è torna una copia di elli à u mittente. Siccomu u servitore solu bisognu di processà un missaghju à u tempu, una architettura iterativa basterà quì. U schedariu di l'intestazione per i servitori hè mostratu in Lista 56.1-XNUMX.

Lista 56.1. File header per i prugrammi id_echo_sv.c è id_echo_cl.c

#include "inet_sockets.h" /* Dichjarà e nostre funzioni di socket */
#include "tlpi_hdr.h"

#define SERVICE "echo" /* Nome di serviziu UDP */

#define BUF_SIZE 500 /* Dimensione massima di datagrammi chì
pò esse lettu da u cliente è u servitore */
________________________________________________________________________ sockets/id_echo.h

Lista 56.2-XNUMX mostra l'implementazione di u servitore. Hè da nutà i seguenti punti:

  • per mette u servitore in modu daemon, usemu a funzione becomeDaemon () da a Sezione 37.2;

  • per fà u prugramma più compactu, usemu a libreria di socket di domini internet sviluppata in a sezione 55.12;

  • se u servitore ùn pò micca rinvià una risposta à u cliente, scrive un missaghju à u logu utilizendu a chjamata syslog().

In una vera applicazione, avaristi prubabilmente impone un certu limitu nantu à a freccia di i missaghji di logu cù syslog (). Questu averebbe eliminà a pussibilità di un attaccu overflowing u log di u sistema. Inoltre, tenite in mente chì ogni chjama di syslog () hè abbastanza caru, postu chì usa fsync () per difettu.

Lista 56.2. Un servitore di iterazione chì implementa u serviziu Echo UDP

_________________________________________________________________sockets/id_echo_sv.c
#include
#include "id_echo.h"
#include "become_daemon.h"

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

if (diventa Daemon (0) == -1)
errExit ("diventa Daemon");

sfd = inetBind (SERVICE, SOCK_DGRAM, NULL);
if (sfd == -1) {
syslog(LOG_ERR, "Ùn si pò micca creà u socket di u servitore (%s)",
strerror(errno));
esce (EXIT_FAILURE);

/* Riceve datagrammi è rinviate copie à i mittenti */
}
per (;;) {
len = sizeof (struct sockaddr_storage);
numRead = recvfrom (sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

if (numRead == -1)
errExit("recvfrom");
if (sendto (sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!=numRead)
syslog(LOG_WARNING, "Errore durante a risposta à %s (%s)",
inetAddressStr((struct sockaddr *) &claddr, len,
addrStr, IS_ADDR_STR_LEN),
strerror(errno));
}
}
_________________________________________________________________sockets/id_echo_sv.c

Utilizemu u prugramma in u listinu 56.3 per pruvà u servitore. Utilizeghja ancu a biblioteca di socket di domini Internet sviluppata in a Sezione 55.12. U prugramma di u cliente piglia u nome di l'ospite di a rete induve u servitore hè situatu cum'è u primu argumentu in a linea di cummanda. U cliente entra in un ciclu induve invià ognuna di l'argumenti rimanenti à u servitore cum'è datagrammi separati, è poi leghje è emette i datagrammi ricevuti da u servitore in risposta.

Lista 56.3. Cliente per u serviziu Echo UDP

#include "id_echo.h"

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

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

/* Formate l'indirizzu di u servitore basatu annantu à u primu argumentu di linea di cumanda */
sfd = inetConnect(argv[1], SERVICE, SOCK_DGRAM);
se (sfd == -1)
fatal ("Ùn pudendu micca cunnette à u socket di u servitore");

/* Mandate u restu di l'argumenti à u servitore cum'è datagrammi separati */
per (j = 2; j < argc; j++) {
len = strlen(argv[j]);
if (scrivite (sfd, argv[j], len) != len)
fatal ("scrittura parziale / falluta");

numRead = leghje (sfd, buf, BUF_SIZE);
if (numRead == -1)
errExit ("leghje");
printf("[%ld bytes] %.*sn", (long) numRead, (int) numRead, buf);
}
esce (EXIT_SUCCESS);
}
_________________________________________________________________sockets/id_echo_cl.c

U seguitu hè un esempiu di ciò chì vedemu quandu avemu principiatu u servitore è duie istanze di cliente:

$ su // Richiede privileggi per legare a un porto riservato
Codice:
# ./id_echo_sv // U servitore passa in fondo
# exit // Rinuncia à i diritti di amministratore
$ ./id_echo_cl localhost hello world // Stu cliente manda dui datagrammi
[5 bytes] ciao // U cliente produce a risposta ricevuta da u servitore
[5 bytes] mondu
$ ./id_echo_cl localhost addiu // Stu cliente manda un datagramma
[7 bytes] addiu

Vi auguru una lettura piacevule)

Source: linux.org.ru