HTTP是一种协议,允许web服务器和浏览器通过互联网进行发送和接受数据,它是一种请求和响应协议,客户端请求一个文件而服务器响应请求。
HTTP请求
一个HTTP请求包括三个组成部分:
方法—统一资源标识符(URI)—协议/版本
请求的头部
主体内容
下面是一个HTTP请求的例子:
POST /examples/default.jsp HTTP/1.1
Accept: text/plain; text/html
Accept-Language: en-gb
Connection: Keep-Alive
Host: localhost
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
Content-Length: 33
Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip, deflate
lastName=Franks&firstName=Michael
方法—统一资源标识符(URI)—协议/版本出现在请求的第一行。
POST /examples/default.jsp HTTP/1.1
这里POST是请求方法,/examples/default.jsp是URI,而HTTP/1.1是协议/版本部分。 每个HTTP请求可以使用HTTP标准里边提到的多种方法之一。HTTP 1.1支持7种类型的请求:GET, POST, HEAD, OPTIONS, PUT, DELETE和TRACE。GET和POST在互联网应用里边最普遍使用的。 URI完全指明了一个互联网资源。URI通常是相对服务器的根目录解释的,因此,始终一斜线/开头。统一资源定位器(URL)其实是一种URI。
请求的头部包含了关于客户端环境和请求的主体内容的有用信息。例如它可能包括浏览器设置的语言,主体内容的长度等等。每个头部通过一个回车换行符(CRLF)来分隔的。 对于HTTP请求格式来说,头部和主体内容之间有一个回车换行符(CRLF)是相当重要的。CRLF告诉HTTP服务器主体内容是在什么地方开始的。在一些互联网编程书籍中,CRLF还被认为是HTTP请求的第四部分。 在前面一个HTTP请求中,主体内容只不过是下面一行:
lastName=Franks&firstName=Michael 实体内容在一个典型的HTTP请求中可以很容易的变得更长。
HTTP响应
类似于HTTP请求,一个HTTP响应也包括三个组成部分:
方法—统一资源标识符(URI)—协议/版本
响应的头部
主体内容
下面是一个HTTP响应的例子:
HTTP/1.1 200 OK
Server: Microsoft-IIS/4.0
Date: Mon, 5 Jan 2004 13:13:33 GMT
Content-Type: text/html
Last-Modified: Mon, 5 Jan 2004 13:13:12 GMT
Content-Length: 112
<html>
<head>
<title>HTTP Response Example</title>
</head>
<body> Welcome to Brainy Software </body> <
/html>
响应头部的第一行类似于请求头部的第一行。第一行告诉你该协议使用HTTP 1.1,请求成功(200=成功),表示一切都运行良好。 响应头部和请求头部类似,也包括很多有用的信息。响应的主体内容是响应本身的HTML内容。头部和主体内容通过CRLF分隔开来。
实例
首先定义三个类:
HttpServer
Request
Response
应用程序的入口点(静态main方法)可以在HttpServer类里边找到。main方法创建了一个HttpServer的实例并调用了它的await方法。await方法,顾名思义就是在一个指定的端口上等待HTTP请求,处理它们并发送响应返回客户端。它一直等待直至接收到shutdown命令。 应用程序不能做什么,除了发送静态资源,例如放在一个特定目录的HTML文件和图像文件。它也在控制台上显示传入的HTTP请求的字节流。不过,它不给浏览器发送任何的头部例如日期或者cookies。
HttpServer代码如下:
package ex01;
import java.net.*;
import java.io.*;
public class HttpServer {
/** WEB_ROOT is the directory where our HTML and other files reside.
* For this package, WEB_ROOT is the "webroot" directory under the
* working directory. * The working directory is the location in the file system
* from where the java command was invoked. */
public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot";
//shutdowm command
private static final String SHUTDOWN_COMMAND="/SHUTDOWN";
// the shutdown command received
private boolean shutdown=false;
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
HttpServer server=new HttpServer();
server.await();
}
public void await(){
ServerSocket serverSocket=null;
int port=8081;
try{
serverSocket=new ServerSocket(port,1,
InetAddress.getByName("127.0.0.1"));
}catch(IOException e){
e.printStackTrace();
System.exit(1);
}
while(!shutdown){
Socket socket=null;
InputStream input=null;
OutputStream output=null;
try{
socket=serverSocket.accept();
input=socket.getInputStream();
output=socket.getOutputStream();
Request request=new Request(input);
request.parse();
Response response=new Response(output);
response.setRequest(request);
response.sendStaticResource();
socket.close();
shutdown=request.getUri().equals(SHUTDOWN_COMMAND);
}catch(Exception e){
e.printStackTrace();
continue;
}
}
}
}
request代码:
package ex01;
import java.io.*;
public class Request {
private InputStream input;
private String uri;
public Request(InputStream input){
this.input=input;
}
public void parse(){
//Read a set of characters from the socket
StringBuffer request=new StringBuffer(2048);
int i;
byte[] buffer=new byte[2048];
try{
i=input.read(buffer);
}catch(IOException e){
e.printStackTrace();
i=-1;
}
for(int j=0;j<i;j++){
request.append((char)buffer[j]);
}
System.out.println(HttpServer.WEB_ROOT);
this.uri=parseUri(request.toString());
System.out.println(uri);
}
public String parseUri(String requestString){
int index1=0,index2=0;
index1=requestString.indexOf(' ');
if(index1!=-1){
index2=requestString.indexOf(' ', index1+1);
if(index2>index1){
return requestString.substring(index1+1, index2);
}
}
return null;
}
public String getUri(){
return uri;
}
}
Response代码:
package ex01;
import java.io.*;
/* *
* HTTP Response = Status-Line
*(( general-header | response-header | entity-header ) CRLF)
CRLF [ message-body ]
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
*/
public class Response {
private static final int BUFFER_SIZE=1024;
Request request;
OutputStream output;
public Response(OutputStream output){
this.output=output;
}
public void setRequest(Request request){
this.request=request;
}
public void sendStaticResource() throws IOException {
byte[] bytes=new byte[BUFFER_SIZE];
FileInputStream fis=null;
try{
File file=new File(HttpServer.WEB_ROOT,request.getUri());
if(file.exists()){
fis=new FileInputStream(file);
int ch=fis.read(bytes,0,BUFFER_SIZE);
while(ch!=-1){
output.write(bytes, 0, BUFFER_SIZE);
ch=fis.read(bytes, 0, BUFFER_SIZE);
}
}
else{
// file not found
String errorMessage = "HTTP/1.1 404 File Not Found\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 23\r\n"
+ "\r\n" + "<h1>File Not Found</h1>";
output.write(errorMessage.getBytes());
}
}catch(Exception e){
e.printStackTrace();
System.out.println("错误发生在这里"+e.toString() );
}finally{
if(fis!=null){
fis.close();
}
}
}
}