بسم الله الرحمن الرحيم
مقدمة:
كثيرا منا لا يعرف أي شي عن برتوكول http وعن كيفية التعامل معه برمجيا باستخدام لغة السي
وقد اًليت عن نفسي الا ان أوضح ألي الأخوة كيفية الاستفادة من هذا البرتوكول وتوضيح نوع التطبيقات التي يستخدم فيها واستخداماته.
ما هو برتوكول http:
هو عبارة عن برتوكول يستخدم في نقل البيانات بين خادم الانترنت وعميل الانترنت حيث يعتبر خادم الانترنت هو احدي مواقع الويب
وعميل الانترنت هو مستعرض الويب. لقد بداء استخدام برتوكول http في الويب منذ عام 1990 . والإصدار الأول
HTTP/0.9 كان إصدار بسيط ولكن الإصدارات التي تليه HTTP/1.0- HTTP/1.1أصبحت أكثر تعقيدا.
يستخدم برتوكول http في كثير من البرامج التي تتعامل مع مواقع الويب ومن أشهر استخدامات برتوكول http هو استخدامه
في مستعرضات الانترنت.
بنية برتوكول http:
يعتمد برتوكول http علي برتوكول TCP/IP في إرسال البيانات والمنفذ الرئيسي هو 80 كما يمكن استخدام منافذ أخري ،
بإمكان برتوكول http إرسال أي نوع من البيانات بين الخادم والعميل وهذا البيان يمكن أن تكون نصوص أو صور أو أي نوع أخر.
منذ الإصدار HTTP/1.0 أصبح إرسال المعلومات عن طريق برتوكول http بطريقة الرسائل النصية.
تحتوي هذه الرسائل علي معلومات meta وتسمي المحتوي، لهذه الرسائل صيغة معينة يمكن معرفتها بالرجوع إلي rfc2068.
الطلب Request والاستجابة Response:
يطلب العميل البيانات من الخادم في صورة رسالة تسمي هذه العملية "طلب " Request ثم يفسر الخادم هذه الرسالة
ويرد علي العميل برسالة وتسمي هذه العملية "استجابة" Response.
تنقسم رسالة الطلب ألي ثلاث أجزء وهي سطر الطلب(Request line) و Request Headers و Body.
يحتوي Request Headers علي معلومات تصف نوع مستعرض العميل و رقم إصدار برتوكول http ومعلومات عامة عن الطلب، يمكن
أن تحتوي رسالة الطلب علي header واحد أو أكثر. الجسم (body) هو محتوي الطلب وهو يصف المعلومات التي يرسلها العميل
(مثل مدخلات form أو بيانات ملف لرفعه إلي الخادم) .
تحتوي رسالة الاستجابة علي سطر الحالة Status-Line و Response headers والجسم .
سطر الحال يصف حالة الرد ان كان هنالك خطا ما (مثلا الصفحة المطلوبة غير موجودة)، اما اذا لم
يكن هنالك خطاء فان الجسم يحتوي علي بيانات الصفحة ألمراده.
برمجة http:
هنالك عدة تقنيات مبنية لتسهيل عملية برمجة برتوكول http ونذكر منها WinInit وهي من أفضل التقنيات لاستخدامات ftp
والاستخدامات الغير معقدة من العمليات البسيطة من جانب العميل. تقنية WinHttp هي أكثر تعقيدا من WinInit وهي الأنسب
للبرامج التي لديها عمليات معقدة وتستخدم في جانب السيرفر والعميل معا ،وهنالك إجراءات Http Api وتستخدم من جانب السيرفر
فقط وتعتبر low-level .
يمكن استخدام السوكت socket طالما أن برتوكول http يعتمد علي tcp/ip في عمليات الإرسال وهي ما سوف نستخدمها في هذا المقال.
لقد استخدمت هذه الطريقة سابقا في برنامج محرر الفريق العربي.
الاتصال بالسيرفر:
يجب عليك أنشاء اتصال بالسيرفر قبل عملية إرسال الطلب ،وتتم بترجمة اسم المجال إلي عنوان IP المناسب وإجراء الاتصال وهذا
يتم بكل سهولة باستخدام socket.
SOCKET socket; WSADATA WsaData; SOCKADDR_IN sin; socket = socket (AF_INET, SOCK_STREAM, 0); if(socket == INVALID_SOCKET) return 0; sin.sin_family = AF_INET; sin.sin_port = htons( (unsigned short)80 ); sin.sin_addr.s_addr = *((DWORD*)(gethostbyname( "www.arabteam2000.com" )->h_addr_list)); if(connect(socket,(LPSOCKADDR)&sin, sizeof(SOCKADDR_IN) == 0) return 0;
إرسال الطلب:
أولا يتم إرسال سطر الطلب ثم الرؤؤس ثم الجسم ويتم فصل الرؤؤس وسطر عن الجسم عن طريق سطر جديد خالي(“\r\n”).
إرسال سطر الطلب:
يحتوي سطر الطلب علي نوع Method و مسار الصفحة المرادة وإصدار برتوكول http، مثلا عند طلب الصفحة الرئيسية باستخدام
GET يكون سطر الطلب بالصورة التالية:
“GET /vb/index.php?t=23 HTTP/1.1\r\n”
send(socket ,“GET * HTTP/1.1\r\n”,strlen(“GET * HTTP/1.1\r\n”),0);
إرسال الرؤؤس:
تنقسم الرؤؤس إلي ثلاث أنواع ، النوع الأول يسمي general header أو الرؤؤس العامة وهي رؤؤس ترسل مع Request و
Response معا أي يمكن إرسالها مع أي منهما، النوع الثاني Request headers وهي رؤؤس خاصة بالطلب
نفسه، إما النوع الثالث فهو entity headers وهي رؤؤس خاصة بالمحتوي .
send(socket ,“accept: */*\r\n”,strlen(“accept: */*\r\n”),0); send(socket ,“User-Agent: mozila 4.0 \r\n”, strlen(“User-Agent: mozila 4.0 \r\n”),0);
إرسال الجسم:
قبل ان يتم ارسال الجسم (المحتوي) يجب اول معرفة حجم المحتوي وتعريفه مسبقا في الرؤؤس ثم ارسال سطر خالي ثم ارسال المحتوي.
send(socket , “Content-Length: 3495 \r\n”,strlen(“Content-Length: 3495 \r\n”),0);
send(socket ,”\r\n”,strlen(“\r\n”),0);
data = m_file.Read(1/*byte*/);
do
{
send(socket ,data,1,0);
}while((data = m_file.Read(1/*byte*/) != 0))