Linux API ном. Цогц гарын авлага»


Linux API ном. Цогц гарын авлага»

Өдрийн мэнд Би та бүхэнд "Linux API" номыг хүргэж байна. Цогц гарын авлага "(номын орчуулга Линукс програмчлалын интерфейс). Үүнийг хэвлэгчийн вэбсайт дээр захиалж болно, хэрэв та сурталчилгааны кодыг хэрэглэвэл LinuxAPI та 30% хөнгөлөлт эдлэх болно.

Шалгах номноос ишлэл:

Сокетууд: серверийн архитектур

Энэ бүлэгт бид давталттай болон зэрэгцээ серверүүдийг зохион бүтээх үндсэн зарчмуудыг авч үзэхээс гадна сервер талын интернет програмуудыг бий болгоход туслах тусгай inetd дэмоныг авч үзэх болно.

Давталт ба зэрэгцээ серверүүд

Сокет дээр суурилсан сүлжээний серверийн хоёр нийтлэг архитектур байдаг:

  • давталттай: сервер нь үйлчлүүлэгчдэд нэг нэгээр нь үйлчилж, эхлээд нэг үйлчлүүлэгчийн хүсэлтийг (эсвэл хэд хэдэн хүсэлтийг) боловсруулж, дараа нь дараагийнх руу шилжих;

  • зэрэгцээ: сервер нь олон үйлчлүүлэгчдэд нэгэн зэрэг үйлчлэх зориулалттай.

44.8-д FIFO дараалалд суурилсан давталтын серверийн жишээг аль хэдийн өгсөн.

Давталтын серверүүд нь зөвхөн үйлчлүүлэгчийн хүсэлтийг маш хурдан боловсруулах боломжтой нөхцөлд л тохиромжтой байдаг, учир нь үйлчлүүлэгч бүр өмнө нь байгаа бусад үйлчлүүлэгчид үйлчлэх хүртэл хүлээх хэрэгтэй болдог. Энэ аргын нийтлэг хэрэглэгдэхүүн бол үйлчлүүлэгч болон серверийн хооронд ганц хүсэлт, хариулт солилцох явдал юм.

Зэрэгцээ серверүүд нь хүсэлт бүрийг боловсруулахад ихээхэн хугацаа шаардагддаг, эсвэл үйлчлүүлэгч болон сервер урт удаан хугацаанд мессеж солилцдог тохиолдолд тохиромжтой. Энэ бүлэгт бид үндсэндээ зэрэгцээ серверүүдийг зохион бүтээх уламжлалт (болон хамгийн хялбар) арга буюу шинэ үйлчлүүлэгч бүрт тусдаа хүүхдийн процесс үүсгэхэд анхаарлаа хандуулах болно. Ийм үйл явц нь үйлчлүүлэгчид үйлчлэх бүх ажлыг гүйцэтгэдэг бөгөөд үүний дараа дуусдаг. Эдгээр процесс тус бүр нь бие даан ажилладаг тул олон үйлчлүүлэгчид нэгэн зэрэг үйлчлэх боломжтой. Серверийн үндсэн процессын (эцэг эх) гол ажил бол шинэ үйлчлүүлэгч бүрт тусдаа хүүхэд үүсгэх явдал юм (өөр нэг процессын оронд та гүйцэтгэлийн хэлхээ үүсгэж болно).

Дараах хэсгүүдэд бид интернетийн домайн залгуур дээр суурилсан давталтын болон зэрэгцээ серверүүдийн жишээг авч үзэх болно. Эдгээр хоёр сервер нь echo үйлчилгээний хялбаршуулсан хувилбарыг (RFC 862) хэрэгжүүлдэг бөгөөд энэ нь үйлчлүүлэгчийн илгээсэн аливаа мессежийн хуулбарыг буцаадаг.

echo давталт udp сервер

Энэ болон дараагийн хэсэгт бид цуурай үйлчилгээний серверүүдийг танилцуулах болно. Энэ нь 7-р порт дээр байдаг бөгөөд UDP болон TCP дээр ажилладаг (энэ порт нь нөөцлөгдсөн тул цуурай серверийг администраторын эрхээр ажиллуулах ёстой).

Echo UDP сервер нь датаграммуудыг байнга уншиж, тэдгээрийн хуулбарыг илгээгчид буцааж өгдөг. Сервер нэг удаад зөвхөн нэг мессежийг боловсруулах шаардлагатай байдаг тул энд давтагдах архитектур хангалттай байх болно. Серверүүдийн толгой файлыг Жагсаалт 56.1-XNUMX-д үзүүлэв.

Жагсаалт 56.1. id_echo_sv.c болон id_echo_cl.c програмын толгой файл

#include "inet_sockets.h" /* Манай сокет функцуудыг зарладаг */
#"tlpi_hdr.h"-г оруулах

#define SERVICE "echo" /* UDP үйлчилгээний нэр */

#define BUF_SIZE 500 /* Датаграммын хамгийн дээд хэмжээ
үйлчлүүлэгч болон сервер унших боломжтой */
______________________________________________________________________ сокетууд/id_echo.h

Жагсаалт 56.2-XNUMX нь серверийн хэрэгжилтийг харуулж байна. Дараахь зүйлийг тэмдэглэх нь зүйтэй.

  • серверийг дэмон горимд оруулахын тулд бид 37.2-р хэсгийн becomeDaemon() функцийг ашигладаг;

  • програмыг илүү авсаархан болгохын тулд бид 55.12 хэсэгт боловсруулсан интернетийн домайн залгуур номын санг ашигладаг;

  • хэрэв сервер клиент рүү хариу өгөх боломжгүй бол syslog() дуудлагыг ашиглан бүртгэлд мессеж бичнэ.

Бодит хэрэглээнд бид syslog() ашиглан мессеж бүртгэх давтамжид тодорхой хязгаарлалт тавих байх. Энэ нь халдагчид системийн бүртгэлийг халах боломжийг үгүй ​​болгоно. Мөн анхдагчаар fsync()-г ашигладаг тул syslog() дуудлага бүр нэлээд үнэтэй байдаг гэдгийг санаарай.

Жагсаалт 56.2. Echo UDP үйлчилгээг хэрэгжүүлдэг давталт сервер

_________________________________________________________________сокет/id_echo_sv.c
#оруулна
#"id_echo.h"-г оруулах
# "become_daemon.h"-г оруулах

INT
үндсэн(int argc, char *argv[])
{
int sfd;
ssize_t тоо Унших;
socklen_tlen;
struct sockaddr_storage claddr;
charbuf[BUF_SIZE];
char addrStr[IS_ADDR_STR_LEN];

хэрэв (Daemon болох(0) == -1)
errExit("Daemon болох");

sfd = inetBind(SERVICE, SOCK_DGRAM, NULL);
хэрэв (sfd == -1) {
syslog(LOG_ERR, "Серверийн залгуур (%s) үүсгэж чадсангүй",
strerror(алдаа));
гарах(EXIT_FAILURE);

/* Датаграмм хүлээн авч, хуулбарыг илгээгчид буцаах */
}
төлөө(;;) {
len = sizeof(struct sockaddr_storage);
numRead = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

хэрэв (numRead == -1)
errExit("recvfrom");
хэрэв (sendto(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!=numRead)
syslog(LOG_WARNING, "%s (%s)-д хариу өгөхөд алдаа гарлаа",
inetAddressStr((struct sockaddr *) &claddr, len,
addrStr, IS_ADDR_STR_LEN),
strerror(алдаа));
}
}
_________________________________________________________________сокет/id_echo_sv.c

Бид серверийг шалгахын тулд 56.3 жагсаалтад байгаа програмыг ашигладаг. Энэ нь мөн 55.12-р хэсэгт боловсруулсан Интернет домайн залгуур номын санг ашигладаг. Үйлчлүүлэгч програм нь командын мөрөнд сервер байрладаг сүлжээний хостын нэрийг эхний аргумент болгон авдаг. Үйлчлүүлэгч нь давталт руу орж, үлдсэн аргумент бүрийг сервер рүү тусдаа датаграм хэлбэрээр илгээж, хариуд нь серверээс хүлээн авсан датаграммуудыг уншиж, гаргана.

Жагсаалт 56.3. Echo UDP үйлчилгээний үйлчлүүлэгч

#"id_echo.h"-г оруулах

INT
үндсэн(int argc, char *argv[])
{
int sfd, j;
size_tlen;
ssize_t тоо Унших;
charbuf[BUF_SIZE];

хэрэв (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s хост мессеж...n", argv[0]);

/* Эхний командын мөрийн аргумент дээр үндэслэн серверийн хаягийг бүрдүүлэх */
sfd = inetConnect(argv[1], SERVICE, SOCK_DGRAM);
хэрэв (sfd == -1)
fatal("Серверийн залгуурт холбогдож чадсангүй");

/* Үлдсэн аргументуудыг сервер рүү тусдаа датаграм хэлбэрээр илгээх */
(j = 2; j < argc; j++) {
len = strlen(argv[j]);
if (write(sfd, argv[j], len) != len)
fatal("хэсэгчилсэн/ амжилтгүй бичих");

numRead = унших (sfd, buf, BUF_SIZE);
хэрэв (numRead == -1)
errExit("унших");
printf("[%ld байт] %.*sn", (урт) numRead, (int) numRead, buf);
}
гарах(EXIT_SUCCESS);
}
_________________________________________________________________сокетууд/id_echo_cl.c

Дараах нь сервер болон үйлчлүүлэгчийн хоёр тохиолдлыг эхлүүлэхэд бид юу харахыг харуулсан жишээ юм.

$ su // Захиалагдсан порттой холбогдохын тулд давуу эрх шаардлагатай
Нууц үг:
# ./id_echo_sv // Сервер арын дэвсгэр рүү ордог
# гарах // Админы эрхээс татгалзах
$ ./id_echo_cl localhost hello world // Энэ үйлчлүүлэгч хоёр датаграмм илгээдэг
[5 байт] сайн уу // Үйлчлүүлэгч серверээс хүлээн авсан хариултыг гаргадаг
[5 байт] ертөнц
$ ./id_echo_cl localhost баяртай // Энэ үйлчлүүлэгч нэг датаграм илгээдэг
[7 байт] баяртай

Би танд таатай уншихыг хүсч байна)

Эх сурвалж: linux.org.ru