0Pricing
C Academy · درس

خادم TCP

قبول الاتصالات

خادم TCP درس مجاني في C Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C Academy 4 دروس في المجموع.

بناء خادم TCP

ينتظر خادم TCP العملاء ويقبل اتصالاتهم. ودورة حياته هي: إنشاء مقبس، وربطه بمنفذ، ثم الاستماع، وبعد ذلك قبول الاتصالات ضمن حلقة.

الخطوة 1: إنشاء المقبس

أنشئ مقبس تدفق لـ IPv4 TCP. وتعني النتيجة السالبة حدوث فشل.

#include <sys/socket.h>
#include <stdio.h>

int make_server_socket(void) {
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) { perror("socket"); }
    return fd;
}

الخطوة 2: السماح بإعادة استخدام العنوان

يبقى المنفذ، افتراضيًا، في حالة TIME_WAIT بعد توقف الخادم، مما يمنع إعادة تشغيله. اضبط SO_REUSEADDR باستخدام setsockopt حتى تتمكن من إعادة الربط فورًا.

#include <sys/socket.h>

void allow_reuse(int fd) {
    int yes = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
}

الخطوة 3: الربط بمنفذ

يربط bind() المقبس بعنوان ومنفذ محليين. ويجعل INADDR_ANY المقبس يستمع على جميع واجهات الشبكة.

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

int bind_port(int fd, unsigned short port) {
    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
    if (bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0) {
        perror("bind"); return -1;
    }
    return 0;
}

الخطوة 4: الاستماع

يضع listen() المقبس في الحالة السلبية، أي الجاهزة للقبول. وتحدد وسيطة backlog عدد الاتصالات المعلّقة التي يمكن للنواة وضعها في قائمة الانتظار.

#include <sys/socket.h>
#include <stdio.h>

int start_listen(int fd) {
    if (listen(fd, 16) < 0) { /* backlog of 16 */
        perror("listen"); return -1;
    }
    return 0;
}

الخطوة 5: قبول الاتصالات

ينتظر accept() حتى يتصل عميل، ثم يعيد مقبسًا جديدًا خاصًا بذلك العميل. ويواصل المقبس الأصلي الاستماع.

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

int accept_one(int listen_fd) {
    struct sockaddr_in cli;
    socklen_t len = sizeof cli;
    int conn = accept(listen_fd, (struct sockaddr *)&cli, &len);
    if (conn < 0) perror("accept");
    return conn;
}

مقبسان ودوران

بعد accept يصبح لديك مقبسان:

  • يواصل المقبس المستمع قبول العملاء الجدد
  • يتواصل مقبس الاتصال مع عميل محدد واحد

أغلق مقبس الاتصال عند الانتهاء من التعامل مع ذلك العميل.

قراءة الطلب

استخدم recv لقراءة بيانات العميل في مخزن مؤقت. وتعني القيمة المعادة 0 أن العميل قطع الاتصال، بينما تعني -1 حدوث خطأ.

#include <sys/socket.h>
#include <stdio.h>

void handle(int conn) {
    char buf[256];
    ssize_t n = recv(conn, buf, sizeof buf - 1, 0);
    if (n > 0) { buf[n] = 0; printf("got: %s\n", buf); }
}

إرسال استجابة

أرسل الرد باستخدام send. وبالنسبة إلى البيانات الكبيرة، كرّر العملية حتى تُرسل جميع البايتات، إذ قد تكتب عملية استدعاء واحدة جزءًا فقط من المخزن المؤقت.

#include <sys/socket.h>
#include <string.h>

void reply(int conn) {
    const char *msg = "hello from server\n";
    size_t left = strlen(msg);
    const char *p = msg;
    while (left > 0) {
        ssize_t n = send(conn, p, left, 0);
        if (n <= 0) break;
        p += n; left -= (size_t)n;
    }
}

حلقة القبول

يقبل الخادم التكراري البسيط عميلًا واحدًا، ويخدمه، ويغلق اتصاله، ثم يعود في حلقة لقبول العميل التالي. وهو يتعامل مع العملاء واحدًا تلو الآخر.

#include <unistd.h>

void serve_loop(int listen_fd, int (*accept_one)(int), void (*handle)(int)) {
    for (;;) {
        int conn = accept_one(listen_fd);
        if (conn < 0) continue;
        handle(conn);
        close(conn); /* done with this client */
    }
}

الإيقاف السلس

أغلق المقبس المستمع عند توقف الخادم، وتعامل مع SIGINT للخروج من الحلقة بطريقة سليمة. أغلق واصفات الملفات دائمًا لتحرير موارد النواة.

اختبار سريع

اختبر مدى فهمك لخوادم TCP.

مراجعة

لقد بنيت خادم TCP خطوةً خطوة.

  • socket، ثم SO_REUSEADDR، ثم bind، ثم listen، ثم accept
  • يعيد accept مقبسًا جديدًا خاصًا بكل عميل
  • استخدم recv/send للتواصل، ثم أغلق الاتصال
  • استخدم حلقة لخدمة العملاء، وتحقّق من كل قيمة معادة

الأسئلة الشائعة

هل درس «خادم TCP» مجاني؟

نعم — نص درس «خادم TCP» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C Academy 4 دروس في المجموع.

ماذا ستتعلم في «خادم TCP»؟

قبول الاتصالات تتمرن على C Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C Academy؟

لا تُشترط خبرة سابقة. C Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «خادم TCP»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C Academy هذا؟

نعم. كل درس في C Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. نظرة عامة على المقابس
  2. خادم TCP
  3. عميل TCP
  4. معالجة عدة عملاء
← العودة إلى C Academy