1. Primeiro, vamos dar uma olhada na estrutura da mensagem http.
1. Solicitar mensagem
Uma mensagem de solicitação HTTP consiste em quatro partes: linha de solicitação, cabeçalho de solicitação, linha em branco e dados de solicitação.
(1) Linha de solicitação
A linha de solicitação consiste em três campos: o campo do método de solicitação, o campo URL e o campo da versão do protocolo HTTP, que são separados por espaços. Por exemplo, GET /index.html HTTP/1.1.
Os métodos de solicitação do protocolo HTTP incluem GET, POST, HEAD, PUT, DELETE, OPTIONS, TRACE e CONNECT. Aqui apresentamos o método GET e o método POST mais comumente usados.
GET: O método GET é usado quando o cliente deseja ler um documento do servidor. O método GET exige que o servidor coloque o recurso localizado pela URL na parte de dados da mensagem de resposta e o envie de volta ao cliente. Ao usar o método GET, os parâmetros de solicitação e os valores correspondentes são anexados ao URL. Um ponto de interrogação ("?") é usado para representar o final do URL e o início dos parâmetros de solicitação. parâmetros é limitado. Por exemplo, /index.jsp?id=100&op=bind.
POST: O método POST pode ser usado quando o cliente fornece muitas informações ao servidor. O método POST encapsula parâmetros de solicitação em dados de solicitação HTTP, aparecendo na forma de nome/valor, e pode transmitir grandes quantidades de dados.
(2)Cabeçalho da solicitação
O cabeçalho da solicitação consiste em pares de palavra-chave/valor, um par por linha, e as palavras-chave e os valores são separados por dois pontos em inglês ":". O cabeçalho da solicitação informa ao servidor sobre a solicitação do cliente. Os cabeçalhos de solicitação típicos são:
User-Agent: O tipo de navegador que gerou a solicitação.
Aceitar: Lista de tipos de conteúdo reconhecidos pelo cliente.
Host: O nome do host solicitado, permitindo que vários nomes de domínio estejam no mesmo endereço IP, ou seja, um host virtual.
(3) Linha em branco
O último cabeçalho de solicitação é seguido por uma linha em branco, caracteres de retorno de carro e alimentação de linha são enviados para notificar o servidor de que não há mais cabeçalhos de solicitação a seguir.
(4)Solicitar dados
Os dados da solicitação não são utilizados no método GET, mas sim no método POST. O método POST é adequado para situações em que os clientes são obrigados a preencher um formulário. Os cabeçalhos de solicitação mais comumente usados relacionados aos dados de solicitação são Content-Type e Content-Length.
2. Mensagem de resposta
O formato da mensagem de resposta é geralmente semelhante ao da mensagem de solicitação, exceto que a primeira linha é diferente. Os leitores podem encontrar a introdução a este aspecto na Internet e não entrarão em detalhes aqui.
2. Implementação do programa
As etapas para implementar o programa são as seguintes:
1. Receba a solicitação do navegador do cliente;
2. Crie um novo thread para tratar a solicitação;
3. Leia os dados da mensagem, determine se a mensagem está correta e analise o conteúdo da mensagem;
4. Crie uma mensagem de resposta e envie ao cliente;
5. Encerre o thread de processamento e processe outras solicitações do cliente;
O código do programa é o seguinte:
visualizar cópia simples para impressão da área de transferência?
importar java.net.*;
importar java.io.*;
importar java.util.*;
importar java.lang.*;
classe pública Servidor Web {
public static void main(String [] args){
porta interna;
ServidorSocket server_socket;
tentar{
porta=Integer.parseInt(args[0]);
}
pegar (Exceção e){
porta=8080;
}
tentar{
server_socket=novo ServerSocket(porta);
System.out.println("WebServer rodando na porta"+server_socket.getLocalPort());
enquanto(verdadeiro){
Soquete socket=server_socket.accept();
System.out.println("Nova conexão aceita"+socket.getInetAddress()+":"+socket.getPort());
//Cria um thread para uma solicitação específica para lidar com a solicitação
tentar{
solicitação httpRequestHandler = novo httpRequestHandler (soquete);
Tópico thread=novo Tópico(solicitação);
thread.start();
}
catch(Exceção e){
System.out.println(e);
}
}
}
catch(IOException e){
System.out.println(e);
}
}
}
//Classe Thread para processar solicitações
classe httpRequestHandler implementa Runnable{
String estática final CRLF="rn";
Tomada de soquete;
Entrada InputStream;
Saída OutputStream;
BufferedReader br;
//Determina se o tipo de arquivo solicitado está correto
booleano tipo de arquivo=true;
//Parâmetros de inicialização
public httpRequestHandler(Socket socket) lança exceção{
this.socket=soquete;
this.input=socket.getInputStream();
this.output=socket.getOutputStream();
this.br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
//Iniciar o tópico
execução nula pública(){
tentar{
processRequest();
}
catch(Exceção e){
System.out.println(e);
}
}
//Função principal para processamento de solicitações
private void processRequest() lança exceção{
enquanto(verdadeiro){
String headerLine=br.readLine();
System.out.println("a solicitação do cliente é"+headerLine);
if(headerLine.equals(CRLF)||headerLine.equals(""))
quebrar;
StringTokenizer s=new StringTokenizer(headerLine);
String temp=s.nextToken();
if(temp.equals("GET")){
String nomeArquivo=s.nextToken();
nomeArquivo="."+NomeArquivo;
FileInputStream fis=null;
booleano fileExists=true;
if(!(nomedoarquivo.endsWith(".htm")||nomedoarquivo.endsWith(".html")))
{
this.fileType=false;
tentar{
fis=new FileInputStream("erro.html");
}
catch(FileNotFoundException e){
arquivoExists=falso;
}
}
outro{
tentar{
fis=new FileInputStream(nomeArquivo);
}
catch(FileNotFoundException e){
arquivoExists=falso;
}
}
String serverLine = "Servidor: um WebServer java simples";
String statusLine=null;
String contentTypeLine = null;
String entidadeBody=null;
String contentLengthLine="erro";
if(fileExists&&this.fileType){
statusLine="HTTP/1.0 200 OK"+CRLF;
contentTypeLine="Tipo de conteúdo:"+this.contentType(fileName)+CRLF;
contentLengthLine="Content-Length:"+(new Integer(fis.available())).toString()+CRLF;
}
outro{
if(fileExists&&this.fileType==false){
statusLine="HTTP/1.0 400 BadRequest"+CRLF;
contentTypeLine="texto/html";
entidadeBody="<HTML>400 Not BadRequest</TITLE></HEAD>"+
"<BODY>400 BadRequest"+
"<br>uso:http://seuNomeHost:porta/"+
"nomeArquivo.html</BODY></HTML>";
}
senão if(fileExists==falso){
statusLine="HTTP/1.0 404 não encontrado"+CRLF;
contentTypeLine="texto/html";
entidadeBody="<HTML>404 não encontrado</TITLE></HEAD>"+
"<BODY>404 não encontrado"+
"<br>uso:http://seuNomeHost:porta/"+
"nomeArquivo.html</BODY></HTML>";
}
}
saída.write(statusLine.getBytes());
saída.write(serverLine.getBytes());
saída.write(contentTypeLine.getBytes());
saída.write(contentLengthLine.getBytes());
saída.write(CRLF.getBytes());
if(fileExists&&this.fileType){
enviarBytes(fis,saída);
fis.close();
}
outro{
saída.write(entityBody.getBytes());
}
}
}
tentar{
saída.close();
close();
soquete.close();
}
catch(Exceção e){}
}
//Envia a página solicitada pelo cliente
private static void sendBytes(FileInputStream fis,OutputStream os) lança exceção{
byte[] buffer=novo byte[1024];
bytes internos = 0;
while((bytes=fis.read(buffer))!=-1){
os.write(buffer,0,bytes);
}
}
//Define o conteúdo do contentType
string estática privada contentType(String fileName){
if(nomedoarquivo.endsWith(".htm")||nomedoarquivo.endsWith(".html")){
retornar "texto/html";
}
return "NomeArquivo";
}