1. Schauen wir uns zunächst die Nachrichtenstruktur von http an.
1. Nachricht anfordern
Eine HTTP-Anforderungsnachricht besteht aus vier Teilen: Anforderungszeile, Anforderungsheader, Leerzeile und Anforderungsdaten. Die folgende Abbildung zeigt das allgemeine Format der Anforderungsnachricht.
(1) Anforderungszeile
Die Anforderungszeile besteht aus drei Feldern: dem Anforderungsmethodenfeld, dem URL-Feld und dem HTTP-Protokollversionsfeld, die durch Leerzeichen getrennt sind. Beispiel: GET /index.html HTTP/1.1.
Zu den Anforderungsmethoden des HTTP-Protokolls gehören GET, POST, HEAD, PUT, DELETE, OPTIONS, TRACE und CONNECT. Hier stellen wir die am häufigsten verwendeten GET-Methoden und POST-Methoden vor.
GET: Die GET-Methode wird verwendet, wenn der Client ein Dokument vom Server lesen möchte. Die GET-Methode erfordert, dass der Server die über die URL gefundene Ressource in den Datenteil der Antwortnachricht einfügt und sie an den Client zurücksendet. Bei Verwendung der GET-Methode werden die Anforderungsparameter und die entsprechenden Werte an die URL angehängt. Ein Fragezeichen („?“) wird verwendet, um das Ende der URL und den Anfang der übergebenen Anforderungsparameter darzustellen Parameter ist begrenzt. Beispiel: /index.jsp?id=100&op=bind.
POST: Die POST-Methode kann verwendet werden, wenn der Client dem Server viele Informationen bereitstellt. Die POST-Methode kapselt Anforderungsparameter in HTTP-Anforderungsdaten, erscheint in Form von Name/Wert und kann große Datenmengen übertragen.
(2)Anforderungsheader
Der Anforderungsheader besteht aus Schlüsselwort-/Wertpaaren, ein Paar pro Zeile, und die Schlüsselwörter und Werte werden durch einen englischen Doppelpunkt „:“ getrennt. Der Anforderungsheader informiert den Server über die Anfrage des Clients. Typische Anforderungsheader sind:
User-Agent: Der Browsertyp, der die Anfrage generiert hat.
Akzeptieren: Liste der vom Client erkannten Inhaltstypen.
Host: Der angeforderte Hostname, der es ermöglicht, dass sich mehrere Domänennamen unter derselben IP-Adresse befinden, also ein virtueller Host.
(3) Leerzeile
Auf den letzten Anforderungsheader folgt eine Leerzeile. Es werden Wagenrücklauf- und Zeilenvorschubzeichen gesendet, um den Server darüber zu informieren, dass keine weiteren Anforderungsheader folgen können.
(4)Daten anfordern
Die Anfragedaten werden nicht in der GET-Methode verwendet, sondern in der POST-Methode. Die POST-Methode eignet sich für Situationen, in denen Kunden ein Formular ausfüllen müssen. Die am häufigsten verwendeten Anforderungsheader im Zusammenhang mit Anforderungsdaten sind Content-Type und Content-Length.
2. Antwortnachricht
Das Format der Antwortnachricht ähnelt im Allgemeinen dem der Anforderungsnachricht, mit der Ausnahme, dass die erste Zeile anders ist. Die Einführung zu diesem Aspekt finden Leser im Internet und werden hier nicht näher erläutert.
2. Umsetzung des Programms
Die Schritte zur Implementierung des Programms sind wie folgt:
1. Empfangen Sie die Anfrage vom Client-Browser;
2. Erstellen Sie einen neuen Thread, um die Anfrage zu bearbeiten.
3. Lesen Sie die Nachrichtendaten, stellen Sie fest, ob die Nachricht korrekt ist, und analysieren Sie den Nachrichteninhalt.
4. Erstellen Sie eine Antwortnachricht und senden Sie sie an den Client.
5. Beenden Sie den Verarbeitungsthread und bearbeiten Sie andere Kundenanfragen.
Der Programmcode lautet wie folgt:
Klartext in Zwischenablage anzeigen und drucken?
java.net importieren.*;
java.io.* importieren;
import java.util.*;
java.lang.* importieren;
öffentliche Klasse WebServer {
public static void main(String [] args){
int-Port;
ServerSocket server_socket;
versuchen{
port=Integer.parseInt(args[0]);
}
Catch (Ausnahme e){
Port=8080;
}
versuchen{
server_socket=neuer ServerSocket(port);
System.out.println("WebServer läuft auf Port"+server_socket.getLocalPort());
while(true){
Socket socket=server_socket.accept();
System.out.println("Neue Verbindung akzeptiert"+socket.getInetAddress()+":"+socket.getPort());
// Einen Thread für eine bestimmte Anfrage erstellen, um die Anfrage zu bearbeiten
versuchen{
httpRequestHandler request=new httpRequestHandler(socket);
Thread thread=neuer Thread(Anfrage);
thread.start();
}
Catch(Ausnahme e){
System.out.println(e);
}
}
}
Catch(IOException e){
System.out.println(e);
}
}
}
//Thread-Klasse zur Verarbeitung von Anfragen
Klasse httpRequestHandler implementiert Runnable{
final static String CRLF="rn";
Steckdose; Steckdose;
InputStream-Eingabe;
OutputStream-Ausgabe;
BufferedReader br;
//Bestimmen Sie, ob der angeforderte Dateityp korrekt ist
boolean fileType=true;
//Initialisierungsparameter
public httpRequestHandler(Socket socket) löst eine Ausnahme aus{
this.socket=socket;
this.input=socket.getInputStream();
this.output=socket.getOutputStream();
this.br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
//Starte den Thread
public void run(){
versuchen{
ProcessRequest();
}
Catch(Ausnahme e){
System.out.println(e);
}
}
//Kernfunktion zur Bearbeitung von Anfragen
private void ProcessRequest() löst eine Ausnahme aus{
while(true){
String headerLine=br.readLine();
System.out.println("die Client-Anfrage ist"+headerLine);
if(headerLine.equals(CRLF)||headerLine.equals(""))
brechen;
StringTokenizer s=new StringTokenizer(headerLine);
String temp=s.nextToken();
if(temp.equals("GET")){
String fileName=s.nextToken();
fileName="."+fileName;
FileInputStream fis=null;
boolean fileExists=true;
if(!(fileName.endsWith(".htm")||fileName.endsWith(".html")))
{
this.fileType=false;
versuchen{
fis=new FileInputStream("error.html");
}
Catch(FileNotFoundException e){
fileExists=false;
}
}
anders{
versuchen{
fis=new FileInputStream(fileName);
}
Catch(FileNotFoundException e){
fileExists=false;
}
}
String serverLine="Server:ein einfacher Java-WebServer";
String statusLine=null;
String contentTypeLine=null;
String-EntityBody=null;
String contentLengthLine="error";
if(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;
}
anders{
if(fileExists&&this.fileType==false){
statusLine="HTTP/1.0 400 BadRequest"+CRLF;
contentTypeLine="text/html";
EntityBody="<HTML>400 Not BadRequest</TITLE></HEAD>"+
„<BODY>400 BadRequest“+
„<br>usage:http://yourHostName:port/“+
"Dateiname.html</BODY></HTML>";
}
sonst if(fileExists==false){
statusLine="HTTP/1.0 404 nicht gefunden"+CRLF;
contentTypeLine="text/html";
entityBody="<HTML>404 Nicht gefunden</TITLE></HEAD>"+
„<BODY>404 nicht gefunden“+
„<br>usage:http://yourHostName:port/“+
"Dateiname.html</BODY></HTML>";
}
}
Output.write(statusLine.getBytes());
Output.write(serverLine.getBytes());
Output.write(contentTypeLine.getBytes());
Ausgabe.write(contentLengthLine.getBytes());
Output.write(CRLF.getBytes());
if(fileExists&&this.fileType){
sendBytes(fis,output);
fis.close();
}
anders{
Output.write(entityBody.getBytes());
}
}
}
versuchen{
Ausgabe.close();
br.close();
socket.close();
}
Catch(Ausnahme e){}
}
//Sende die vom Client angeforderte Seite
private static void sendBytes(FileInputStream fis,OutputStream os) löst eine Ausnahme aus{
byte[] buffer=neues Byte[1024];
int Bytes=0;
while((bytes=fis.read(buffer))!=-1){
os.write(buffer,0,bytes);
}
}
//Legen Sie den Inhalt von contentType fest
privater statischer String contentType(String fileName){
if(fileName.endsWith(".htm")||fileName.endsWith(".html")){
return „text/html“;
}
return „Dateiname“;
}