كتاب لينكس API. الدليل الشامل »


كتاب لينكس API. الدليل الشامل »

مساء الخير أوجه انتباهكم إلى كتاب "Linux API. الدليل الشامل "(ترجمة الكتاب واجهة برمجة لينكس). يمكن طلبه على موقع الناشر، وإذا قمت بتطبيق الرمز الترويجي LinuxAPI سوف تحصل على خصم 30%.

مقتطف من الكتاب للمراجعة:

المقابس: بنية الخادم

سنناقش في هذا الفصل أساسيات تصميم الخوادم التكرارية والمتوازية، بالإضافة إلى برنامج inetd خاص يسهل إنشاء تطبيقات الإنترنت من جانب الخادم.

التكرار والخوادم المتوازية

هناك نوعان من بنيات خادم الشبكة الشائعة القائمة على المقبس:

  • تكراري: يخدم الخادم العملاء واحدًا تلو الآخر، حيث يقوم أولاً بمعالجة الطلب (أو عدة طلبات) من عميل واحد ثم الانتقال إلى العميل التالي؛

  • الموازي: تم تصميم الخادم لخدمة عملاء متعددين في نفس الوقت.

لقد قدم القسم 44.8 بالفعل مثالاً لخادم تكرار يعتمد على قوائم انتظار FIFO.

عادةً ما تكون خوادم التكرار مناسبة فقط في المواقف التي يمكن فيها معالجة طلبات العميل بسرعة إلى حد ما، حيث يتعين على كل عميل الانتظار حتى تتم خدمة أي عملاء آخرين أمامه. إحدى حالات الاستخدام الشائعة لهذا الأسلوب هي تبادل الطلبات والاستجابات الفردية بين العميل والخادم.

تعد الخوادم المتوازية مناسبة في الحالات التي يستغرق فيها كل طلب وقتًا طويلاً للمعالجة، أو عندما يكون لدى العميل والخادم تبادل طويل للرسائل. في هذا الفصل، سنركز بشكل أساسي على الطريقة التقليدية (والأسهل) لتصميم الخوادم المتوازية، وهي إنشاء عملية فرعية منفصلة لكل عميل جديد. مثل هذه العملية تقوم بكل عمل خدمة العميل، وبعد ذلك تنتهي. وبما أن كل من هذه العمليات تعمل بشكل مستقل، فمن الممكن خدمة عملاء متعددين في نفس الوقت. تتمثل المهمة الرئيسية لعملية الخادم الرئيسية (الأصل) في إنشاء فرع منفصل لكل عميل جديد (بدلاً من ذلك، بدلاً من العمليات، يمكنك إنشاء سلاسل تنفيذ).

في الأقسام التالية، سنلقي نظرة على أمثلة للخوادم التكرارية والمتوازية القائمة على مآخذ مجال الإنترنت. يقوم هذان الخادمان بتطبيق نسخة مبسطة من خدمة الصدى (RFC 862) التي تقوم بإرجاع نسخة من أي رسالة مرسلة إليها من قبل العميل.

خادم 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 تنفيذ الخادم. ومن الجدير بالذكر النقاط التالية:

  • ولوضع الخادم في الوضع الخفي، نستخدم الدالة betaDaemon() من القسم 37.2؛

  • ولجعل البرنامج أكثر إحكاما، نستخدم مكتبة مقبس مجال الإنترنت التي تم تطويرها في القسم 55.12؛

  • إذا لم يتمكن الخادم من إرجاع استجابة إلى العميل، فإنه يكتب رسالة إلى السجل باستخدام استدعاء syslog().

في التطبيق الحقيقي، من المرجح أن نفرض حدًا معينًا على تكرار تسجيل الرسائل باستخدام syslog(). سيؤدي هذا إلى القضاء على احتمال تجاوز المهاجم لسجل النظام. ضع في اعتبارك أيضًا أن كل استدعاء syslog()‎ مكلف جدًا، لأنه يستخدم fsync() افتراضيًا.

قائمة 56.2. خادم تكرار يقوم بتنفيذ خدمة echo UDP

_________________________________________________________________sockets/id_echo_sv.c
#يشمل
#تتضمن "id_echo.h"
#تتضمن "become_daemon.h"

مادبا
main (int argc، char * argv [])
{
إنت سفد؛
ssize_t numRead؛
socklen_tlen;
هيكل sockaddr_storage claddr؛
charbuf[BUF_SIZE];
char addrStr[IS_ADDR_STR_LEN];

إذا (تصبح Daemon(0) == -1)
errExit("becomeDaemon");

sfd = inetBind(SERVICE, SOCK_DGRAM, NULL);
إذا (sfd == -1) {
سجل النظام (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");
إذا (sendto(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!=عدد القراءة)
سجل النظام (LOG_WARNING، "حدث خطأ أثناء تكرار الاستجابة لـ %s (%s)"،
inetAddressStr((struct sockaddr *) &claddr, len,
addrStr، IS_ADDR_STR_LEN)،
strerror (errno)) ؛
}
}
_________________________________________________________________sockets/id_echo_sv.c

نستخدم البرنامج الموجود في القائمة 56.3 لاختبار الخادم. ويستخدم أيضًا مكتبة مقبس مجال الإنترنت التي تم تطويرها في القسم 55.12. يأخذ برنامج العميل اسم مضيف الشبكة حيث يوجد الخادم كوسيطة أولى في سطر الأوامر. يدخل العميل حلقة حيث يرسل كل من الوسيطات المتبقية إلى الخادم كمخططات بيانات منفصلة، ​​ثم يقرأ ويخرج مخططات البيانات المستلمة من الخادم استجابةً لذلك.

قائمة 56.3. عميل لخدمة صدى UDP

#تتضمن "id_echo.h"

مادبا
main (int argc، char * argv [])
{
إنت سفد، ي؛
size_tlen;
ssize_t numRead؛
charbuf[BUF_SIZE];

إذا (argc < 2 || strcmp(argv[1], "--help") == 0)
useErr("%s host msg…n", argv[0]);

/* قم بتكوين عنوان الخادم بناءً على وسيطة سطر الأوامر الأولى */
sfd = inetConnect(argv[1], SERVICE, SOCK_DGRAM);
إذا (sfd == -1)
فادح ("تعذر الاتصال بمقبس الخادم")؛

/* أرسل بقية الوسائط إلى الخادم كمخططات بيانات منفصلة */
لـ (j = 2; j < argc; j++) {
len = strlen(argv[j]);
إذا (اكتب (sfd، argv [j]، لين) ! = لين)
فادح ("كتابة جزئية/فشلت")؛

numRead = read(sfd, buf, BUF_SIZE);
إذا (numRead == -1)
errExit("قراءة");
printf("[%ld bytes] %.*sn", (long) numRead, (int) numRead, buf);
}
خروج (EXIT_SUCCESS) ،
}
_________________________________________________________________sockets/id_echo_cl.c

فيما يلي مثال لما سنراه عندما نبدأ تشغيل الخادم ومثيلين للعميل:

$ su // يتطلب امتيازات للربط بمنفذ محجوز
كلمه السر:
# ./id_echo_sv // يذهب الخادم إلى الخلفية
# خروج // التنازل عن حقوق المسؤول
$ ./id_echo_cl localhost helloworld // يرسل هذا العميل مخططي بيانات
[5 بايت] مرحبًا // يقوم العميل بإخراج الاستجابة المستلمة من الخادم
[5 بايت] العالم
$ ./id_echo_cl وداعًا للمضيف المحلي // يرسل هذا العميل مخطط بيانات واحدًا
[7 بايت] وداعا

أتمنى لك قراءة ممتعة)

المصدر: linux.org.ru