1. أولاً، دعونا نلقي نظرة على بنية رسالة http.
1. رسالة الطلب
تتكون رسالة طلب HTTP من أربعة أجزاء: سطر الطلب، ورأس الطلب، والسطر الفارغ، وبيانات الطلب. ويوضح الشكل التالي التنسيق العام لرسالة الطلب.
(1) خط الطلب
يتكون سطر الطلب من ثلاثة حقول: حقل طريقة الطلب، وحقل URL، وحقل إصدار بروتوكول HTTP، مفصولة بمسافات. على سبيل المثال، احصل على /index.html HTTP/1.1.
تتضمن أساليب الطلب لبروتوكول HTTP GET وPOST وHEAD وPUT وDELETE وOPTIONS وTRACE وCONNECT. نقدم هنا طريقة GET وطريقة POST الأكثر استخدامًا.
GET: يتم استخدام طريقة GET عندما يريد العميل قراءة مستند من الخادم. تتطلب طريقة GET من الخادم وضع المورد الموجود بواسطة عنوان URL في جزء البيانات من رسالة الاستجابة وإرساله مرة أخرى إلى العميل. عند استخدام طريقة GET، يتم إلحاق معلمات الطلب والقيم المقابلة بعنوان URL، ويتم استخدام علامة الاستفهام ("؟") لتمثيل نهاية عنوان URL وبداية معلمات الطلب المعلمات محدودة. على سبيل المثال، /index.jsp?id=100&op=bind.
POST: يمكن استخدام طريقة POST عندما يقدم العميل الكثير من المعلومات إلى الخادم. تقوم طريقة POST بتغليف معلمات الطلب في بيانات طلب HTTP، والتي تظهر في شكل اسم/قيمة، ويمكنها نقل كميات كبيرة من البيانات.
(٢) رأس الطلب
يتكون رأس الطلب من أزواج الكلمات الرئيسية/القيم، وزوج واحد في كل سطر، ويتم فصل الكلمات الرئيسية والقيم بنقطتين إنجليزيتين: ". يُعلم رأس الطلب الخادم بطلب العميل، ورؤوس الطلب النموذجية هي:
وكيل المستخدم: نوع المتصفح الذي أنشأ الطلب.
قبول: قائمة أنواع المحتوى التي يتعرف عليها العميل.
المضيف: اسم المضيف المطلوب، مما يسمح بأن تكون أسماء النطاقات المتعددة على نفس عنوان IP، أي مضيف افتراضي.
(3) سطر فارغ
يتبع رأس الطلب الأخير سطر فارغ، ويتم إرسال حرف إرجاع وأحرف تغذية السطر لإعلام الخادم بأنه لم يعد هناك المزيد من رؤوس الطلبات التي يجب متابعتها.
(4)طلب البيانات
لا يتم استخدام بيانات الطلب في طريقة GET، ولكن في طريقة POST. تعد طريقة POST مناسبة للمواقف التي يُطلب فيها من العملاء ملء نموذج. رؤوس الطلبات الأكثر استخدامًا والمتعلقة ببيانات الطلب هي نوع المحتوى وطول المحتوى.
2. رسالة الرد
ويشبه تنسيق رسالة الرد بشكل عام رسالة الطلب، إلا أن السطر الأول مختلف. ويمكن للقراء العثور على مقدمة لهذا الجانب على الإنترنت ولن يدخلوا في التفاصيل هنا.
2. تنفيذ البرنامج
وخطوات تنفيذ البرنامج هي كما يلي:
1. تلقي الطلب من متصفح العميل.
2. قم بإنشاء موضوع جديد للتعامل مع الطلب؛
3. قراءة بيانات الرسالة وتحديد مدى صحة الرسالة وتحليل محتوى الرسالة؛
4. إنشاء رسالة رد وإرسالها إلى العميل.
5. إنهاء سلسلة المعالجة ومعالجة طلبات العملاء الأخرى؛
رمز البرنامج هو كما يلي:
عرض نسخة عادية إلى الحافظة؟
استيراد java.net.*;
استيراد java.io.*;
import java.util.*;
import java.lang.*;
خادم الويب من الفئة العامة {
الفراغ الثابت العام الرئيسي (String [] args) {
ميناء كثافة العمليات.
ServerSocket server_socket;
يحاول{
port=Integer.parseInt(args[0]);
}
قبض (استثناء ه){
المنفذ=8080;
}
يحاول{
server_socket=new ServerSocket(port);
System.out.println("خادم الويب يعمل على المنفذ"+server_socket.getLocalPort());
بينما (صحيح) {
مقبس المقبس=server_socket.accept();
System.out.println("تم قبول الاتصال الجديد"+socket.getInetAddress()+":":+socket.getPort());
// أنشئ موضوعًا لطلب محدد للتعامل مع الطلب
يحاول{
httpRequestHandler request=new httpRequestHandler(socket);
موضوع الموضوع = موضوع جديد (طلب)؛
Thread.start();
}
قبض (استثناء ه) {
System.out.println(e);
}
}
}
قبض (IOException ه) {
System.out.println(e);
}
}
}
// فئة الموضوع لمعالجة الطلبات
فئة httpRequestHandler تنفذ Runnable{
السلسلة الثابتة النهائية CRLF = "rn"؛
مقبس المقبس
إدخال تيار الإدخال؛
إخراج تيار الإخراج؛
BufferedReader ر؛
// تحديد ما إذا كان نوع الملف المطلوب صحيحًا
نوع الملف المنطقي = صحيح؛
// معلمات التهيئة
httpRequestHandler العام (مأخذ التوصيل) يطرح استثناءً {
this.socket=socket;
this.input=socket.getInputStream();
this.output=socket.getOutputStream();
this.br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
// ابدأ الموضوع
تشغيل الفراغ العام () {
يحاول{
معالجة طلب();
}
قبض (استثناء ه) {
System.out.println(e);
}
}
// الوظيفة الأساسية لمعالجة الطلبات
عملية باطلة خاصة () تطرح استثناءً {
بينما (صحيح) {
String headerLine=br.readLine();
System.out.println("طلب العميل هو"+headerLine);
إذا (headerLine.equals(CRLF)||headerLine.equals(""))
استراحة؛
StringTokenizer s=new StringTokenizer(headerLine);
String temp=s.nextToken();
إذا (temp.equals("GET")){
String fileName=s.nextToken();
fileName = "."+fileName؛
FileInputStream fis=null;
boolean fileExists=true;
إذا(!(fileName.endsWith(".htm")||fileName.endsWith(".html")))
{
this.fileType=false;
يحاول{
fis=new FileInputStream("error.html");
}
قبض على (FileNotFoundException ه) {
fileExists=false;
}
}
آخر{
يحاول{
fis=new FileInputStream(fileName);
}
قبض على (FileNotFoundException ه) {
fileExists=false;
}
}
String serverLine = "الخادم: خادم ويب جافا بسيط"؛
String StatusLine=null;
String contentTypeLine=null;
StringentityBody=null;
سلسلة contentLengthLine = "خطأ"؛
إذا (fileExists&&this.fileType){
StatusLine="HTTP/1.0 200 OK"+CRLF;
contentTypeLine="Content-type:"+this.contentType(fileName)+CRLF;
contentLengthLine="Content-Length:"+(new Integer(fis.available())).toString()+CRLF;
}
آخر{
إذا (fileExists&&this.fileType==false){
StatusLine="HTTP/1.0 400 BadRequest"+CRLF;
contentTypeLine="text/html";
الكيان Body="<HTML>400 ليس طلبًا سيئًا</TITLE></HEAD>"+
"<BODY>400 طلب سيئ"+
"<br>الاستخدام:http://yourHostName:port/"+
"fileName.html</BODY></HTML>";
}
آخر إذا(fileExists==خطأ){
StatusLine="HTTP/1.0 404 لم يتم العثور عليه"+CRLF;
contentTypeLine="text/html";
الكيان = "<HTML>404 لم يتم العثور عليه</TITLE></HEAD>"+
"<BODY>404 غير موجود"+
"<br>الاستخدام:http://yourHostName:port/"+
"fileName.html</BODY></HTML>";
}
}
Output.write(statusLine.getBytes());
output.write(serverLine.getBytes());
Output.write(contentTypeLine.getBytes());
input.write(contentLengthLine.getBytes());
input.write(CRLF.getBytes());
إذا (fileExists&&this.fileType){
sendBytes(fis,output);
fis. Close();
}
آخر{
input.write(entityBody.getBytes());
}
}
}
يحاول{
الإخراج. إغلاق ()؛
br. Close();
المقبس. إغلاق ()؛
}
قبض (الاستثناء ه) {}
}
// أرسل الصفحة التي طلبها العميل
إرسال بايت ثابت خاص (FileInputStream fis،OutputStream os) يطرح استثناءً {
بايت[] المخزن المؤقت=بايت جديد[1024];
بايت بايت = 0؛
بينما((بايت=fis.read(المخزن المؤقت))!=-1){
os.write(buffer,0,bytes);
}
}
// قم بتعيين محتوى contentType
نوع محتوى السلسلة الثابتة الخاصة (اسم ملف السلسلة) {
إذا(fileName.endsWith(".htm")||fileName.endsWith(".html")){
إرجاع "نص/أتش تي أم أل"؛
}
إرجاع "اسم الملف"؛
}