مميزEngineeringDone

ft_irc — خادم IRC مكتوب من الصفر بلغة C++98

خادم IRC متوافق مع RFC مكتوب بلغة C++98، يخدم عملاء متعددين في خيط واحد عبر poll، ويدعم القنوات وأوضاعها وصلاحيات المشغّلين.

٢٢ يوليو ٢٠٢٦
3 التقنيات
English
ft_irc — خادم IRC مكتوب من الصفر بلغة C++98

عن هذا المشروع

خادم IRC مبني من الصفر بلغة C++98 باستخدام مقابس TCP وحلقة أحداث عبر poll، مع دعم القنوات وصلاحيات المشغّلين والرسائل الخاصة.

التقنيات

C++NetworkingSystems Programming

i99dev_project_ft-irc_cover_1200x630_v1.0.0.svg

مشروع ضمن مسار 42 أبوظبي — بناء خادم IRC كامل بلغة C++98 دون الاعتماد على أي مكتبة شبكات خارجية.

نظرة عامة

ft_irc خادم دردشة يطبّق بروتوكول IRC كما تصفه معايير RFC، مكتوب بالكامل بلغة C++98. يقبل الخادم اتصالات من عملاء IRC حقيقيين مثل irssi و_HexChat_، ويتعامل مع عشرات الجلسات المتزامنة داخل خيط تنفيذ واحد.

make
./ircserv <port> <password>

المشكلة

كتابة خادم شبكي حقيقي تفرض ثلاث مشكلات لا يمكن الالتفاف عليها:

  1. التزامن دون خيوط. يجب خدمة عملاء كثيرين في آن واحد، مع منع أي عميل بطيء من تعطيل البقية.
  2. البروتوكول النصي. رسائل IRC تصل مجزّأة عبر TCP؛ لا ضمان بأن تصل الرسالة كاملة أو منفردة.
  3. قيد اللغة. C++98 دون auto ولا unique_ptr ولا خيوط قياسية — إدارة الذاكرة ودورة حياة الكائنات مسؤولية يدوية بالكامل.

التخطيط

قبل كتابة أي سطر، قُسّم المشروع إلى أربع طبقات مستقلة يمكن اختبار كل منها على حدة:

الطبقة المسؤولية
طبقة المقابس قبول الاتصالات وقراءة/كتابة البايتات
طبقة التقطيع تحويل تدفق البايتات إلى رسائل مكتملة
طبقة التحليل تفكيك الرسالة إلى بادئة وأمر ووسائط
طبقة الأوامر تنفيذ منطق كل أمر وإصدار الردود

الفصل بين التقطيع و_التحليل_ كان القرار الأهم: بدونه يتسرّب تعامل الشبكة إلى منطق الأوامر ويصبح الاختبار مستحيلاً.

القرارات المعمارية

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

مقابس غير حاجزة مع مخزن لكل عميل. لكل اتصال مخزن دخل ومخزن خرج. القراءة تُلحق البايتات بمخزن الدخل، ثم تُستخرج الرسائل المنتهية بـ \r\n فقط. الكتابة لا تحدث مباشرة بل تُصفّ في مخزن الخرج ويُرسل ما تسمح به النواة عند جاهزية المقبس — وهذا ما يمنع العميل البطيء من تجميد الخادم.

جدول أوامر بدل سلسلة if****. كل أمر (NICK، USER، JOIN، PRIVMSG، KICK، MODE، INVITE، TOPIC) يُسجّل في جدول يربط الاسم بمعالجه، فإضافة أمر جديد لا تمسّ منطق التوجيه.

التنفيذ

دورة حياة الاتصال تمرّ بمصادقة إلزامية قبل أي شيء آخر: PASS ثم NICK ثم USER. أي أمر يصل قبل اكتمالها يُقابل برقم الخطأ المناسب حسب المعيار.

بعد المصادقة يفتح الخادم الأوامر الكاملة:

  • القنوات — إنشاء وانضمام ومغادرة، مع بثّ الرسائل إلى جميع الأعضاء عدا المُرسِل.
  • صلاحيات المشغّلKICK وINVITE وTOPIC وMODE، مع التحقق من الصلاحية قبل التنفيذ.
  • أوضاع القناة+i للدعوة فقط، +t لقصر تعديل الموضوع على المشغّلين، +k لكلمة مرور القناة، +o لمنح الإشراف، +l لحدّ الأعضاء.
  • الرسائل الخاصةPRIVMSG بين المستخدمين وإلى القنوات.
  • حيوية الاتصالPING/PONG لكشف الجلسات الميتة، وQUIT للانفصال النظيف.
  • أوامر الاستعلامWHOIS لعرض بيانات مستخدم (الاسم الحقيقي، المضيف، والقنوات المنضم إليها)، وLIST لاستعراض قنوات الخادم مع مواضيعها وعدد أعضائها.

وأوضاع القناة تُضبط بصيغة المعيار الكاملة:

/mode <channel> {[+|-]|o|p|s|i|t|n|b|v} [<limit>] [<user>] [<ban mask>]

الردود تتبع أرقام المعيار (RPL_ وERR_)، وهو ما يجعل العملاء الحقيقيين يعرضونها بشكل صحيح دون أي تخصيص.

النتيجة والدروس

الخادم يعمل مع عملاء IRC تجاريين دون تعديل، ويصمد أمام الاتصال والانفصال المتكرر ورسائل التدفق العالي.

  1. TCP تدفق لا رسائل. أي خادم نصي يحتاج طبقة تقطيع صريحة؛ افتراض أن recv تُرجع رسالة كاملة خطأ يظهر متأخراً وتحت الحمل فقط.
  2. صفّ الخرج ليس تحسيناً. بدونه تتحول send إلى نقطة تجميد للخادم كله عند أول عميل بطيء.
  3. قيود اللغة تُحسِّن التصميم. غياب أدوات C++ الحديثة فرض حدوداً واضحة بين الطبقات وملكية صريحة للكائنات.

الروابط

روابط المشروع

تاريخ البداية٢٢ يوليو ٢٠٢٦
الحالةDone

مشاركة المشروع