本文是学习《Tomcat深入剖析》后,对书中内容对总结,主要用于自己学习记录,纯手打。。。
Http请求分为三部分:
1、请求方法-------统一资源标识符--------协议/版本
2、请求头
3、实体(实体和请求头之间有一个空行)
如下:
GET /sample.jsp HTTP/1.1
Accept:image/gif.image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
Accept-Encoding:gzip,deflate
username=jinqiao&password=1234
Http响应同样分为三部分:1、协议-----状态码-----描述
2、响应头
3、响应实体(响应头和响应实体之间有一个空行)
如下:
HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 122
<html>
<head>
<title>Wrox Homepage</title>
</head>
<body>
<!-- body goes here -->
</body>
</html>
下面是一个例子(包括三个类:MyHttpServer,Request,Response),用浏览器访问本机IP地址和端口号,然后再控制台输出对应的内容。
====================分割线====================
import Java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.NET.InetAddress;
import java.Net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
/**
*
* MyHttpServer类主要作用:
* 设置服务器根路径WEB_ROOT
* new一个SeverSocket实例监听对应的端口当有响应到达时,调用accept方法返回一个Socket实例
* 获取Socket实例的输入输出流,使用自定义的Request对输入流按照Http协议进行解析,Response则按照Http协议进行数据的发送
*/
public class MyHttpServer {
/**
* 设置服务器根目录,里面存放各种资源
* 注意:“webroot”后面如果有分隔符则表示“webroot”是一个目录,下面还有子文件,如果后面没有分隔符则表示“webroot”是一个具体的文件
*/
public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"WebRoot"+File.separator;
/**
* 定义服务关闭指令
*/
private static final String SHUTDOWN_COMMAND="/SHUTDOWN";
/**
* 定义服务器关闭状态,默认为false
*/
private boolean shutdown=false;
public static void main(String[] args){
MyHttpServer myMailServer=new MyHttpServer();
myMailServer.await();
}
public void await(){
ServerSocket serverSocket=null;
/**
* 指定服务器默认监听端口
*/
int port = 8888;
/**
* 指定服务器请求队列最大长度
*/
int backlog=1;
/**
* 指定serverSocket监听的主机
*/
InetAddress address= null;
try {
address= InetAddress.getByName("127.0.0.1");
serverSocket=new ServerSocket(port, backlog, address);
}catch(UnknownHostException e){
e.printStackTrace();
System.exit(1);
}catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
System.out.println("服务器已成功启动");
while(!shutdown){
Socket socket=null;
InputStream inputStream=null;
OutputStream outputStream=null;
try {
/**
* 当没有请求到达时,accept()会一直等待
*/
socket=serverSocket.accept();
System.out.println("服务器收到一个请求");
inputStream=socket.getInputStream();
outputStream=socket.getOutputStream();
/**
* 构建一个Request类,用以解析Http请求的原始数据
*/
Request request =new Request(inputStream);
/**
* 解析Http请求
*/
request.parse();
/**
* 构建一个Response类,用以返回请求
*/
Response response=new Response(outputStream);
/**
* 设置response,为返回请求做准备
*/
response.setRequest(request);
/**
* 判断Http请求静态资源还是servlet
*/
response.sendStaticResource();
socket.close();
shutdown=request.getUri().equals(SHUTDOWN_COMMAND);
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("服务器关闭");
}
}
====================分割线====================
import java.io.IOException;
import java.io.InputStream;
public class Request {
private InputStream inputStream;
private String uri;
/**
* 创建Request时传入一个InputStream对象
*/
public Request(InputStream inputStream) {
this.inputStream=inputStream;
}
public void parse() {
/**
* 定义一个StringBuffer对象,用以存储InputStream中传入的数据
*/
StringBuffer request=new StringBuffer(2048);
byte[] bytes=new byte[2048];
int i=-1;
try {
/**
* 读取inputStream中的数据,并把读取的存入一个byte数组中
*/
i=this.inputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
for(int j=0;j<i;j++){
/**
* 将byte数组中的数据放入StringBuffer中
*/
request.append((char)bytes[j]);
}
System.out.println(request.toString());
this.uri=parseUri(request.toString());
}
private String parseUri(String requestString){
int index1,index2;
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 this.uri;
}
}====================分割线====================
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
public class Response {
/**
* 定义一个默认缓存字节长度
*/
private static final int BUFFER_SIZE=1024;
private OutputStream outputStream;
/**
* 定义一个request对象,获取request中的uri
*/
private Request request;
public Response(OutputStream outputStream) {
this.outputStream=outputStream;
}
public void setRequest(Request request) {
this.request=request;
}
public void sendStaticResource() {
byte[] bytes=new byte[BUFFER_SIZE];
FileInputStream fis=null;
try {
/**
* 加载请求资源文件
*/
File file=null;
try{
file=new File(MyHttpServer.WEB_ROOT,request.getUri());
System.out.println("请求资源绝对路径"+file.getAbsolutePath());
}catch(NullPointerException e){
}
if(file.exists()){
fis=new FileInputStream(file);
/**
* 读取file,每次读取长度为BUFFER_SIZE
*/
int ch=fis.read(bytes, 0, BUFFER_SIZE);
while(ch!=-1){
this.outputStream.write(bytes, 0, ch);
ch=fis.read(bytes, 0, BUFFER_SIZE);
}
}else{
System.out.println("请求资源不存在");
String errorMessage="HTTP/1.1 404 File Not Found\r\n"+
"Context-Type:text/html\r\n"+
"Context-Length:23\r\n"+
"\r\n"+
"<h1>File Not Found</h1>";
this.outputStream.write(errorMessage.getBytes());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
====================分割线====================
程序启动后,在浏览器输入127.0.0.1:8888后,控制台显示如下:
服务器已成功启动
服务器收到一个请求
GET /123.html HTTP/1.1
Host: 127.0.0.1:8888
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8,und;q=0.6
请求资源绝对路径F:\JAVA\MyHttpServer1.0\WebRoot\123.html
浏览器显示:
1744

被折叠的 条评论
为什么被折叠?



