مقدمة: لماذا كتابة عميل HTTP بلغة C++؟
في التطوير الحديث، التفاعل مع الخوادم البعيدة هو إحدى المهام الأساسية. سواء كان الحصول على بيانات من REST API، أو إرسال نموذج إلى الخادم، أو تحميل ملف - في كل مكان يُستخدم بروتوكول HTTP. على الرغم من أن Python و JavaScript تقدم حلولاً مدمجة بسيطة، إلا أن C++ تظل مطلوبة لكتابة عملاء HTTP عاليي الأداء. هذا ضروري للأنظمة المدمجة، ومحركات الألعاب، والخوادم الخلفية عالية التحميل، أو ببساطة لدراسة آليات الشبكة منخفضة المستوى.
في هذه المقالة، سنناقش نهجين شائعين لتنفيذ عميل HTTP بلغة C++: استخدام مكتبة libcurl (cURL) والنهج غير المتزامن الأكثر حداثة مع Boost.Beast. ستتعلم كيفية تكوين طلبات GET و POST بشكل صحيح، ومعالجة الردود، وتجنب الأخطاء النموذجية.
1. النهج الكلاسيكي: عميل HTTP بلغة C++ مع libcurl
مكتبة libcurl هي أداة مثبتة عبر الزمن لنقل البيانات عبر بروتوكولات مختلفة. تدعم HTTP/1.1 و HTTP/2 و HTTPS والمصادقة والكوكيز وغير ذلك الكثير. بالنسبة لـ C++، يوجد غلاف مناسب curl/curl.h يسمح بدمج cURL بسهولة في مشروعك.
تثبيت libcurl
في معظم توزيعات Linux، cURL مثبت بالفعل. للتطوير، ستحتاج إلى حزمة المطور:
sudo apt-get install libcurl4-openssl-dev # Ubuntu/Debianbrew install curl # macOSمثال: طلب GET
لنكتب عميل HTTP بسيط بلغة C++ يحصل على بيانات من API عام (مثل JSONPlaceholder).
#include <iostream>#include <string>#include <curl/curl.h>
// Callback لكتابة البيانات في std::stringstatic size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { ((std::string*)userp)->append((char*)contents, size * nmemb); return size * nmemb;}
int main() { CURL *curl; CURLcode res; std::string readBuffer;
curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init();
if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts/1"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // تنفيذ الطلب res = curl_easy_perform(curl); if(res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "رد الخادم:" << readBuffer << std::endl; } curl_easy_cleanup(curl); } curl_global_cleanup(); return 0;}مثال: طلب POST مع JSON
الآن سنرسل بيانات إلى الخادم. للقيام بذلك، نحتاج إلى تحديد نوع المحتوى ونص الطلب.
#include <iostream>#include <string>#include <curl/curl.h>
int main() { CURL *curl; CURLcode res; std::string response; // بيانات JSON للإرسال std::string jsonData = R"({"title": "foo", "body": "bar", "userId": 1})"; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts"); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str()); // تعيين الرؤوس struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // Callback لكتابة الرد curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, [](void *contents, size_t size, size_t nmemb, void *userp) -> siz