Књига Линук АПИ-ја. Свеобухватан водич»


Књига Линук АПИ-ја. Свеобухватан водич»

Добар дан Представљам вам књигу „Линук АПИ. Свеобухватан водич“ (превод књиге Линук програмски интерфејс). Може се наручити на веб страници издавача и ако примените промотивни код ЛинукАПИ добићете попуст од 30%.

Одломак из књиге за рецензију:

Утичнице: серверска архитектура

У овом поглављу ћемо разговарати о основама пројектовања итеративних и паралелних сервера, као ио специјалном инетд демону који олакшава креирање Интернет апликација на страни сервера.

Итерација и паралелни сервери

Постоје две уобичајене архитектуре мрежног сервера засноване на сокету:

  • итеративно: сервер опслужује клијенте једног по једног, прво обрађује захтев (или неколико захтева) једног клијента, а затим прелази на следећег;

  • паралелно: сервер је дизајниран да опслужује више клијената у исто време.

Одељак 44.8 је већ дао пример итерационог сервера заснованог на ФИФО редовима.

Итерацијски сервери су обично прикладни само у ситуацијама у којима се захтеви клијената могу обрадити прилично брзо, јер сваки клијент мора да чека док се други клијенти испред њега не услуже. Уобичајени случај употребе овог приступа је размена појединачних захтева и одговора између клијента и сервера.

Паралелни сервери су погодни у случајевима када је за обраду сваког захтева потребно доста времена, или када клијент и сервер имају дугу размену порука. У овом поглављу ћемо се углавном фокусирати на традиционални (и најлакши) начин дизајнирања паралелних сервера, а то је стварање посебног подређеног процеса за сваког новог клијента. Такав процес обавља сав посао услуживања клијента, након чега се завршава. Пошто сваки од ових процеса функционише независно, могуће је истовремено опслуживати више клијената. Главни задатак главног серверског процеса (родитеља) је да креира посебно дете за сваког новог клијента (алтернативно, уместо процеса, можете креирати нити извршавања).

У следећим одељцима ћемо погледати примере итеративних и паралелних сервера заснованих на утичницама интернет домена. Ова два сервера имплементирају поједностављену верзију ехо сервиса (РФЦ 862) која враћа копију било које поруке коју му пошаље клијент.

ецхо итерација удп сервер

У овом и следећем одељку ћемо представити сервере за ехо сервис. Доступан је на порту број 7 и ради и преко УДП-а и ТЦП-а (овај порт је резервисан, па стога ехо сервер мора да се покреће са администраторским привилегијама).

Ецхо УДП сервер стално чита датаграме и враћа копију пошиљаоцу. Пошто сервер треба да обрађује само једну по једну поруку, овде ће бити довољна итеративна архитектура. Датотека заглавља за сервере је приказана на Листингу 56.1-XNUMX.

Листинг 56.1. Датотека заглавља за програме ид_ецхо_св.ц и ид_ецхо_цл.ц

#инцлуде "инет_соцкетс.х" /* Декларише наше функције сокета */
#инцлуде "тлпи_хдр.х"

#дефине СЕРВИЦЕ "ецхо" /* УДП име услуге */

#дефине БУФ_СИЗЕ 500 /* Максимална величина датаграма који
могу читати клијент и сервер */
________________________________________________________________________ соцкетс/ид_ецхо.х

Листинг 56.2-XNUMX приказује имплементацију сервера. Вреди напоменути следеће тачке:

  • да бисмо сервер поставили у демонски режим, користимо функцију бецомеДаемон() из одељка 37.2;

  • да бисмо програм учинили компактнијим, користимо библиотеку соцкета интернет домена развијену у одељку 55.12;

  • ако сервер не може да врати одговор клијенту, он уписује поруку у дневник користећи сислог() позив.

У стварној апликацији, највероватније бисмо наметнули одређено ограничење учесталости евидентирања порука помоћу сислог(). Ово би елиминисало могућност да нападач препуни системски дневник. Такође, имајте на уму да је сваки позив сислог() прилично скуп, пошто подразумевано користи фсинц().

Листинг 56.2. Итерацијски сервер који имплементира ецхо УДП услугу

___________________________________________________________________соцкетс/ид_ецхо_св.ц
#инцлуде
#инцлуде "ид_ецхо.х"
#инцлуде "бецоме_даемон.х"

инт
маин(инт аргц, цхар *аргв[])
{
инт сфд;
ссизе_т нумРеад;
соцклен_тлен;
струцт соцкаддр_стораге цладдр;
цхарбуф[БУФ_СИЗЕ];
цхар аддрСтр[ИС_АДДР_СТР_ЛЕН];

иф (бецомеДаемон(0) == -1)
еррЕкит("бецомеДаемон");

сфд = инетБинд(СЕРВИЦЕ, СОЦК_ДГРАМ, НУЛЛ);
ако (сфд == -1) {
сислог(ЛОГ_ЕРР, "Не могу креирати утичницу сервера (%с)",
стреррор(еррно));
екит(ЕКСИТ_ФАИЛУРЕ);

/* Примајте датаграме и враћајте копије пошиљаоцима */
}
за(;;) {
лен = сизеоф(струцт соцкаддр_стораге);
нумРеад = рецвфром(сфд, буф, БУФ_СИЗЕ, 0, (струцт соцкаддр *) &цладдр, &лен);

иф (нумРеад == -1)
еррЕкит("рецвфром");
иф (сендто(сфд, буф, нумРеад, 0, (струцт соцкаддр *) &цладдр, лен)
!=нумРеад)
сислог(ЛОГ_ВАРНИНГ, "Грешка при ехо одговору на %с (%с)",
инетАддрессСтр((струцт соцкаддр *) &цладдр, лен,
аддрСтр, ИС_АДДР_СТР_ЛЕН),
стреррор(еррно));
}
}
___________________________________________________________________соцкетс/ид_ецхо_св.ц

Користимо програм у листингу 56.3 да тестирамо сервер. Такође користи библиотеку соцкета интернет домена развијену у одељку 55.12. Клијентски програм узима име мрежног хоста на коме се сервер налази као први аргумент у командној линији. Клијент улази у петљу где сваки од преосталих аргумената шаље серверу као засебне датаграме, а затим чита и шаље датаграме примљене од сервера као одговор.

Листинг 56.3. Клијент за ецхо УДП услугу

#инцлуде "ид_ецхо.х"

инт
маин(инт аргц, цхар *аргв[])
{
инт сфд,ј;
сизе_тлен;
ссизе_т нумРеад;
цхарбуф[БУФ_СИЗЕ];

иф (аргц < 2 || стрцмп(аргв[1], "--хелп") == 0)
усагеЕрр("%с хост мсг…н", аргв[0]);

/* Формирајте адресу сервера на основу првог аргумента командне линије */
сфд = инетЦоннецт(аргв[1], СЕРВИЦЕ, СОЦК_ДГРАМ);
ако (сфд == -1)
фатал("Не могу да се повежем на утичницу сервера");

/* Пошаљите остатак аргумената серверу као засебне датаграме */
за (ј = 2; ј < аргц; ј++) {
лен = стрлен(аргв[ј]);
иф (врите(сфд, аргв[ј], лен) != лен)
фатал("делимично/неуспешно писање");

нумРеад = реад(сфд, буф, БУФ_СИЗЕ);
иф (нумРеад == -1)
еррЕкит("читај");
принтф("[%лд бајтова] %.*сн", (дуго) нумРеад, (инт) нумРеад, буф);
}
екит(ЕКСИТ_СУЦЦЕСС);
}
___________________________________________________________________соцкетс/ид_ецхо_цл.ц

Следи пример онога што ћемо видети када покренемо сервер и две клијентске инстанце:

$ су // Захтева привилегије за повезивање са резервисаним портом
пассворд:
# ./ид_ецхо_св // Сервер иде у позадину
# излаз // Одустајемо од администраторских права
$ ./ид_ецхо_цл лоцалхост хелло ворлд // Овај клијент шаље два датаграма
[5 бајтова] здраво // Клијент шаље одговор примљен од сервера
[5 бајтова] свет
$ ./ид_ецхо_цл лоцалхост збогом // Овај клијент шаље један датаграм
[7 бајтова] збогом

Желим вам пријатно читање)

Извор: линук.орг.ру