Liburua β€œLinux API. Gida integrala"


Liburua β€œLinux API. Gida integrala"

Arratsalde on β€œLinux API. Gida integrala" (liburuaren itzulpena Linux Programazio Interfazea). Argitaletxearen webgunean eska daiteke, eta promozio kodea aplikatuz gero LinuxAPI , %30eko deskontua izango duzu.

Liburuaren zatia erreferentzia gisa:

Socketak: Zerbitzariaren Arkitektura

Kapitulu honetan, zerbitzari iteratiboak eta paraleloak diseinatzeko oinarriak aztertuko ditugu, eta inetd izeneko deabru berezi bat ere aztertuko dugu, Interneteko zerbitzariaren aplikazioak sortzea errazten duena.

Zerbitzari iteratiboak eta paraleloak

Socketetan oinarritutako sare-zerbitzariaren arkitektura arruntak daude:

  • iteratiboa: zerbitzariak bezeroak banan-banan zerbitzatzen ditu, lehenik bezero baten eskaera bat (edo hainbat eskaera) prozesatzen du eta gero hurrengora igaroz;

  • paraleloa: zerbitzaria hainbat bezero aldi berean zerbitzatzeko diseinatuta dago.

FIFO ilaretan oinarritutako zerbitzari iteratibo baten adibidea dagoeneko aurkeztu zen 44.8 atalean.

Zerbitzari iteratiboak normalean bezeroen eskaerak nahiko azkar prozesatu daitezkeen egoeretan baino ez dira egokiak, bezero bakoitzak aurrean dituen beste bezero batzuk zerbitzatu arte itxaron behar baitute. Ikuspegi honen ohiko erabilera kasu bat bezero eta zerbitzari baten artean eskaera eta erantzun bakarren trukea da.

Zerbitzari paraleloak egokiak dira eskaera bakoitzak prozesatzeko denbora handia behar duen kasuetan, edo bezeroak eta zerbitzariak mezu-truke luzeetan parte hartzen duten kasuetan. Kapitulu honetan, zerbitzari paraleloak diseinatzeko modu tradizionalean (eta errazenean) zentratuko gara batez ere, hau da, bezero berri bakoitzarentzako prozesu seme-alaba bereizia sortzea. Prozesu honek bezeroari zerbitzatzeko lan guztia egiten du eta gero amaitzen da. Prozesu horietako bakoitzak modu independentean funtzionatzen duenez, posible da hainbat bezero aldi berean zerbitzatzea. Zerbitzariaren prozesu nagusiaren (gurasoa) zeregin nagusia bezero berri bakoitzeko seme-alaba bereizia sortzea da (bestela, prozesuen ordez exekuzio hariak sor daitezke).

Hurrengo ataletan, interneteko domeinu socket zerbitzari iteratibo eta paraleloen adibideak ikusiko ditugu. Bi zerbitzari hauek oihartzun zerbitzuaren bertsio sinplifikatu bat ezartzen dute (RFC 862), bezero batek bidalitako edozein mezuren kopia itzultzen duena.

UDP zerbitzariaren oihartzuna errepikakorra

Atal honetan eta hurrengoan oihartzun zerbitzurako zerbitzariak aurkeztuko ditugu. 7. zenbakian dago erabilgarri eta UDP zein TCP bidez funtzionatzen du (ataka hau erreserbatuta dago, eta, beraz, echo zerbitzaria administratzaile-pribilegioekin exekutatu behar da).

Echo UDP zerbitzariak etengabe irakurtzen ditu datagramak eta horien kopiak itzultzen dizkio igorleari. Zerbitzariak aldi berean mezu bakarra prozesatu behar duenez, nahikoa izango da arkitektura errepikakorra. Zerbitzarien goiburuko fitxategia 56.1 zerrendan agertzen da.

Zerrenda 56.1. Id_echo_sv.c eta id_echo_cl.c programen goiburuko fitxategia

#include "inet_sockets.h" /* Gure socketaren funtzioak deklaratzen ditu */
#include "tlpi_hdr.h"

#define SERVICE "oihartzuna" /* UDP zerbitzuaren izena */

#define BUF_SIZE 500 /* Datagramen gehienezko tamaina hori
bezeroak eta zerbitzariak irakur daitezke */
___________________________________________________________________________sockets/id_echo.h

56.2 zerrendak zerbitzariaren inplementazioa erakusten du. Nabarmentzekoak dira puntu hauek:

  • zerbitzaria deabru moduan jartzeko, 37.2 ataleko becomeDaemon() funtzioa erabiltzen dugu;

  • Programa trinkoagoa izateko, Interneteko domeinu-socketekin lan egiteko liburutegia erabiltzen dugu, 55.12 atalean garatua;

  • zerbitzariak ezin badu erantzunik itzuli bezeroari, mezu bat idazten du erregistroan syslog() deia erabiliz.

Benetako aplikazio batean, ziurrenik, syslog() erabiliz mezuak erregistratzeko maiztasunari mugaren bat ezarriko genioke. Horrek erasotzaile batek sistemaren erregistroa gainezka egiteko aukera ezabatuko luke. Gainera, ez ahaztu syslog()-rako dei bakoitza nahiko garestia dela, fsync() erabiltzen baitu lehenespenez.

Zerrenda 56.2. UDP oihartzun zerbitzua inplementatzen duen iterazio zerbitzaria

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

int
main(int argc, char *argv[])
{
int sfd;
size_t numRead;
socklen_t len;
struct sockaddr_storage claddr;
char buf[BUF_SIZE];
char addrStr[IS_ADDR_STR_LEN];

bada (bihurtuDaemon(0) == -1)
errExit("bihurtuDaemon");

sfd = inetBind (ZERBITZUA, SOCK_DGRAM, NULL);
bada (sfd == -1) {
syslog(LOG_ERR, "Ezin izan da sortu zerbitzariaren socket (%s)",
strerror(errno));
irten(EXIT_FAILURE);

/* Datagramak jaso eta igorleei horien kopiak itzuli */
}
(;;) {
len = sizeof(struct sockaddr_storage);
numRead = recvfrom (sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

bada (zenbakiaIrakurri == -1)
errExit("recvfrom");
if (sendto(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!= numIrakurri)
syslog(LOG_WARNING, "Errorea %s (%s)-ren erantzuna oihartzunean",
inetAddressStr((struct sockaddr *) &claddr, len,
addrStr, IS_ADDR_STR_LEN),
strerror(errno));
}
}
_________________________________________________________________sockets/id_echo_sv.c

Zerbitzariaren funtzionamendua probatzeko, 56.3 zerrendako programa erabiltzen dugu. Liburutegia ere erabiltzen du Interneteko domeinu-socketekin lan egiteko, 55.12 atalean garatua. Komando-lerroko lehen argumentu gisa, bezero-programak zerbitzaria dagoen sare-nodoaren izena hartzen du. Bezeroak begizta batean sartzen du non gainerako argumentu bakoitza zerbitzariari bidaltzen dion datagrama bereizi gisa, eta ondoren zerbitzaritik jasotzen dituen datagramak irakurtzen eta inprimatzen ditu erantzun moduan.

Zerrenda 56.3. UDP oihartzun zerbitzurako bezeroa

#include "id_echo.h"

int
main(int argc, char *argv[])
{
int sfd, j;
size_t len;
size_t numRead;
char buf[BUF_SIZE];

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

/* Eratu zerbitzariaren helbidea komando lerroko lehen argumentuan oinarrituta */
sfd = inetConnect (argv[1], ZERBITZUA, SOCK_DGRAM);
bada (sfd == -1)
fatal("Ezin izan da zerbitzariaren socketera konektatu");

/* Bidali gainerako argumentuak zerbitzariari datagrama bereizi moduan */
for (j = 2; j < argc; j++) {
len = strlen(argv[j]);
bada (idatzi(sfd, argv[j], len) != len)
fatal ("idazketa partziala/huts egin");

numRead = irakurri (sfd, buf, BUF_SIZE);
bada (zenbakiaIrakurri == -1)
errExit ("irakurtu");
printf("[%ld bytes] %.*sn", (long) numRead, (int) numRead, buf);
}
irten (EXIT_SUCCESS);
}
_________________________________________________________________sockets/id_echo_cl.c

Jarraian zerbitzaria eta bi bezero instantzia exekutatzean ikusiko dugunaren adibidea da:

$su // Pribilegioak behar dira erreserbatutako ataka batera lotzeko
Pasahitza:
# ./id_echo_sv // Zerbitzaria atzeko planoan sartzen da
# irten // Administratzaile eskubideak utzi
$ ./id_echo_cl localhost kaixo mundua // Bezero honek bi datagrama bidaltzen ditu
[5 byte] kaixo // Bezeroak zerbitzaritik jasotako erantzuna bistaratzen du
[5 byte] mundua
$ ./id_echo_cl localhost agur // Bezero honek datagrama bat bidaltzen du
[7 byte] agur

Irakurketa atsegina opa dizut)

Iturria: linux.org.ru