کتاب API لینوکس. راهنمای جامع »


کتاب API لینوکس. راهنمای جامع »

عصر بخیر کتاب “Linux API. راهنمای جامع» (ترجمه کتاب رابط برنامه نویسی لینوکس). می توان آن را در وب سایت ناشر سفارش داد و اگر کد تبلیغاتی را اعمال کنید LinuxAPI ، از 30 درصد تخفیف برخوردار خواهید شد.

گزیده ای از کتاب برای مرجع:

سوکت ها: معماری سرور

در این فصل به مبانی طراحی سرورهای تکراری و موازی می پردازیم و همچنین به دیمون ویژه ای به نام inetd می پردازیم که ایجاد برنامه های کاربردی سرور اینترنتی را آسان می کند.

سرورهای تکراری و موازی

دو معماری رایج سرور شبکه مبتنی بر سوکت وجود دارد:

  • تکرار شونده: سرور در یک زمان به مشتریان سرویس می دهد، ابتدا یک درخواست (یا چندین درخواست) از یک مشتری را پردازش می کند و سپس به سراغ بعدی می رود.

  • موازی: سرور برای سرویس دهی به چندین مشتری به طور همزمان طراحی شده است.

نمونه ای از یک سرور تکراری مبتنی بر صف های FIFO قبلاً در بخش 44.8 ارائه شده است.

سرورهای تکرار شونده معمولاً فقط در شرایطی مناسب هستند که درخواست‌های مشتری می‌توانند نسبتاً سریع پردازش شوند، زیرا هر کلاینت مجبور است منتظر بماند تا سایر کلاینت‌های روبروی خود ارائه شوند. یک مورد استفاده رایج برای این رویکرد، تبادل درخواست ها و پاسخ های منفرد بین مشتری و سرور است.

سرورهای موازی در مواردی مناسب هستند که پردازش هر درخواست زمان قابل توجهی را می طلبد، یا زمانی که مشتری و سرور درگیر تبادل پیام طولانی هستند. در این فصل، ما عمدتاً بر روی روش سنتی (و ساده‌ترین) طراحی سرورهای موازی تمرکز خواهیم کرد، که عبارت است از ایجاد یک فرآیند فرزند جداگانه برای هر مشتری جدید. این فرآیند تمام کارها را برای خدمت به مشتری انجام می دهد و سپس به پایان می رسد. از آنجا که هر یک از این فرآیندها به طور مستقل عمل می کنند، امکان ارائه خدمات به چندین مشتری به طور همزمان وجود دارد. وظیفه اصلی فرآیند سرور اصلی (والد) ایجاد یک فرزند جداگانه برای هر کلاینت جدید است (به طور متناوب، می توان رشته های اجرا را به جای پردازش ها ایجاد کرد).

در بخش‌های بعدی، نمونه‌هایی از سرورهای سوکت دامنه اینترنتی تکراری و موازی را بررسی خواهیم کرد. این دو سرور یک نسخه ساده شده از سرویس اکو (RFC 862) را پیاده سازی می کنند، که یک کپی از هر پیامی که توسط مشتری به آن ارسال شده است را برمی گرداند.

اکو سرور UDP تکراری

در این قسمت و قسمت بعدی سرورهای سرویس اکو را معرفی خواهیم کرد. در پورت شماره 7 موجود است و روی هر دو UDP و TCP کار می کند (این پورت رزرو شده است و بنابراین سرور اکو باید با امتیازات مدیر اجرا شود).

سرور UDP echo به طور مداوم دیتاگرام ها را می خواند و کپی هایی از آنها را به فرستنده برمی گرداند. از آنجایی که سرور تنها نیاز به پردازش یک پیام در یک زمان دارد، یک معماری تکراری کافی است. فایل هدر برای سرورها در فهرست 56.1 نشان داده شده است.

فهرست 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 اجرای سرور را نشان می دهد. نکات زیر قابل توجه است:

  • برای قرار دادن سرور در حالت daemon، از تابع ()bereDaemon از بخش 37.2 استفاده می کنیم.

  • برای فشرده‌تر کردن برنامه، از کتابخانه برای کار با سوکت‌های دامنه اینترنت، که در بخش 55.12 توسعه یافته است، استفاده می‌کنیم.

  • اگر سرور نتواند پاسخی را به کلاینت بازگرداند، با استفاده از فراخوانی ()syslog پیامی را به گزارش می نویسد.

در یک برنامه واقعی، ما احتمالاً محدودیتی را بر فرکانس ثبت پیام ها با استفاده از ()syslog اعمال می کنیم. این امکان را از بین می برد که مهاجم از لاگ سیستم سرریز کند. علاوه بر این، فراموش نکنید که هر فراخوانی به syslog() بسیار گران است، زیرا به طور پیش فرض از fsync() استفاده می کند.

فهرست 56.2. سرور تکراری که سرویس UDP echo را پیاده سازی می کند

_________________________________________________________________ سوکت ها/id_echo_sv.c
#عبارتند از
#include "id_echo.h"
#شامل "become_daemon.h"

INT
اصلی (int argc، char *argv[])
{
int sfd;
ssize_t numRead;
socklen_t len;
struct sockaddr_storage claddr;
char buf[BUF_SIZE];
char adrStr[IS_ADDR_STR_LEN];

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

sfd = inetBind(SERVICE، SOCK_DGRAM، NULL);
اگر (sfd == -1) {
syslog(LOG_ERR، "نمی توان سوکت سرور ایجاد کرد (%s)"،
strerror (errno));
خروج (EXIT_FAILURE)؛

/* دیتاگرام ها را دریافت کنید و کپی هایی از آنها را به فرستنده بازگردانید */
}
برای (؛؛) {
len = sizeof(struct sockaddr_storage);
numRead = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

اگر (numRead == -1)
errExit("recvfrom");
if (sendto(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!= numRead)
syslog(LOG_WARNING، "خطا در بازتاب پاسخ به %s (%s)"،
inetAddressStr((struct sockaddr *) &claddr, len,
adrStr، IS_ADDR_STR_LEN)،
strerror (errno));
}
}
_________________________________________________________________ سوکت ها/id_echo_sv.c

برای تست عملکرد سرور، از برنامه لیست 56.3 استفاده می کنیم. همچنین از کتابخانه برای کار با سوکت های دامنه اینترنتی، توسعه یافته در بخش 55.12 استفاده می کند. به عنوان اولین آرگومان خط فرمان، برنامه مشتری نام گره شبکه ای را می گیرد که سرور در آن قرار دارد. کلاینت وارد حلقه ای می شود که در آن هر یک از آرگومان های باقی مانده را به عنوان دیتاگرام جداگانه به سرور ارسال می کند و سپس دیتاگرام هایی را که از سرور دریافت می کند در پاسخ می خواند و چاپ می کند.

فهرست 56.3. مشتری برای سرویس UDP echo

#include "id_echo.h"

INT
اصلی (int argc، char *argv[])
{
int sfd, j;
اندازه_t len;
ssize_t numRead;
char buf[BUF_SIZE];

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

/* آدرس سرور را بر اساس اولین آرگومان خط فرمان تشکیل دهید */
sfd = inetConnect(argv[1]، SERVICE، SOCK_DGRAM);
اگر (sfd == -1)
fatal ("نمی توان به سوکت سرور متصل شد");

/* آرگومان های باقیمانده را در قالب دیتاگرام های جداگانه به سرور ارسال کنید */
برای (j = 2; j < argc; j++) {
len = strlen(argv[j]);
اگر (نوشتن(sfd، argv[j]، len) != len)
fatal ("نوشتن جزئی / ناموفق");

numRead = خواندن (sfd، buf، BUF_SIZE)؛
اگر (numRead == -1)
errExit ("خواندن");
printf("[%ld bytes] %.*sn", (long) 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