برمجة الشبكات بلغة C++: من المقابس إلى البرمجة غير المتزامنة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

برمجة الشبكات بلغة C++: من المقابس إلى البرمجة غير المتزامنة

\n\n

هل تساءلت يومًا كيف تعمل الدردشات، الألعاب عبر الإنترنت، أو خوادم الويب؟ في قلب كل منها يوجد التفاعل الشبكي. وإذا كنت تريد كتابة تطبيقات شبكية سريعة وموثوقة ومنخفضة المستوى، فإن برمجة الشبكات بلغة C++ هي ما تحتاجه. في هذه المقالة، لن نمر فقط على النظري، بل سنكتب كودًا حقيقيًا: من دردشة TCP بسيطة إلى خادم غير متزامن باستخدام Boost.Asio. جهّز بيئات التطوير الخاصة بك - سيكون الأمر ممتعًا!

\n\n

لماذا C++ للشبكات؟ ثلاثة أسباب

\n

يختار الكثيرون Python أو Java للمهام الشبكية، لكن C++ تقدم ثلاث مزايا رئيسية:

\n
    \n
  • السرعة: تكاليف إضافية ضئيلة، وصول مباشر لاستدعاءات النظام (syscalls).
  • \n
  • التحكم: أنت تدير الذاكرة، المخازن المؤقتة، والتوقيتات يدويًا.
  • \n
  • النظام البيئي: Boost.Asio، libcurl، Poco - مكتبات قوية لأي مهمة.
  • \n
\n

لكن مع القوة العظيمة تأتي مسؤولية عظيمة: خطأ واحد في إدارة المقبس - وسيسقط خادمك. دعنا نفهم كيف نتجنب ذلك.

\n\n

الأساسيات: المقابس ونموذج OSI

\n

قبل كتابة الكود، لنتذكر ما هو المقبس. إنه تجريد يسمح للتطبيق بإرسال واستقبال البيانات عبر الشبكة. في C++ نعمل من خلال sys/socket.h (لينكس) أو winsock2.h (ويندوز).

\n\n

TCP مقابل UDP: متى نستخدم أيهما؟

\n
    \n
  • TCP (SOCK_STREAM): يضمن التسليم وترتيب الحزم. مثالي للدردشات، HTTP، قواعد البيانات.
  • \n
  • UDP (SOCK_DGRAM): أسرع، لكن بدون ضمانات. يُستخدم في البث المباشر، DNS، الألعاب عبر الإنترنت (حيث فقدان الحزمة أسهل من التأخير).
  • \n
\n\n

كتابة خادم وعميل TCP بلغة C++ (مقابس نقية)

\n

لنقم بإنشاء خادم صدى بسيط. يستقبل رسالة ويعيد إرسالها. هذا هو "Hello, World" الكلاسيكي في برمجة الشبكات بلغة C++.

\n\n

جزء الخادم (echo_server.cpp)

\n
#include <iostream>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <unistd.h>\n#include <cstring>\n\nint main() {\n    int server_fd, client_fd;\n    struct sockaddr_in address;\n    int opt = 1;\n    int addrlen = sizeof(address);\n    char buffer[1024] = {0};\n\n    // 1. إنشاء مقبس\n    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {\n        perror("socket failed");\n        exit(EXIT_FAILURE);\n    }\n\n    // 2. ربط بالمنفذ (خيار إعادة استخدام المنفذ)\n    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {\n        perror("setsockopt");\n        exit(EXIT_FAILURE);\n    }\n    address.sin_family = AF_INET;\n    address.sin_addr.s_addr = INADDR_ANY;\n    address.sin_port = htons(8080);\n\n    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {\n        perror("bind failed");\n        exit(EXIT_FAILURE);\n    }\n\n    // 3. الاستماع للاتصالات الواردة\n    if (listen(server_fd, 3) < 0) {\n        perror("listen");\n        exit(EXIT_FAILURE);\n    }\n\n    std::cout << "الخادم يعمل على المنفذ 8080. في انتظار الاتصالات..." << std::endl;\n\n    // 4. قبول العميل\n    if ((client_fd = accept(server_fd, (struct sockaddr *)&address,\n                            (socklen_t*)&addrlen)) < 0) {\n        perror("accept");\n        exit(EXIT_FAILURE);\n    }\n\n    // 5. القراءة والإرسال مرة أخرى (الصدى)\n    int valread = read(client_fd, buffer, 1024);\n    std::cout << "تم الاستلام: " << buffer << std::endl;\n    send(client_fd, buffer, strlen(buffer), 0);\n    std::cout << "تم إرسال رد الصدى" << std::endl;\n\n    close(client_fd);\n    close(server_fd);\n    return 0;\n}
\n\n

جزء العميل (echo_client.cpp)

\n
#include <                

المدونات

توصيات الكتب