主要内容:本节的主要内容介绍了http请求和响应报文,并且编写了一个简单的http服务器的例子,来说明java是如何创建web服务的。这个例子使用了三个类来实现分别是:
-
HttpServer:主要用来接收浏览器的请求,并且创建Request对象和Response对象来进行请求资源的提取和对应返回给浏览器对应的数据。
-
Request:主要用来提取请求报文中数据,提取uri
-
Response:主要用来向浏览器返回对应的请求数据。
下面分别给出上述三个类的实现,这里作者的这种写法很面向对象,值得我们学习。
1.HttpServer
package demon1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer {
private static final String SHUTDOWN_COMMAND="/shutdown";
private boolean shutdown=false;
private static final int PORT=8080;
private static final String IP="127.0.0.1";
public void await(){
ServerSocket serverSocket=null;
try {
serverSocket=new ServerSocket(PORT,1, InetAddress.getByName(IP));
} catch (IOException e) {
e.printStackTrace();
}
//等价于while(true),只是比他更加的灵活
while(!shutdown){
try {
assert serverSocket != null;
//阻塞监听端口
Socket socket = serverSocket.accept();
//输入流,包含请求报文
InputStream inputStream = socket.getInputStream();
Request request=new Request(inputStream);
request.parse();
//输出流,向浏览器写入输出报文
OutputStream outputStream = socket.getOutputStream();
Response response=new Response(outputStream);
response.setRequest(request);
response.sendStaticResource();
socket.close();
shutdown=request.getUri().equals(SHUTDOWN_COMMAND);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.Request
package demon1;
import java.io.IOException;
import java.io.InputStream;
public class Request {
/**
* 输入流
*/
private InputStream input;
/**
* 请求的资源
*/
private String uri;
public Request(InputStream input) {
this.input = input;
}
/**
* 解析报文方法
*/
public void parse(){
StringBuilder stringBuilder = new StringBuilder(2048);
int readSum=0;
byte[] buffer=new byte[2048];
try {
readSum= input.read(buffer);
} catch (IOException e) {
e.printStackTrace();
}
for(int j=0;j<readSum;j++){
stringBuilder.append((char) buffer[j]);
}
//解析请求资源
uri=parseUri(stringBuilder.toString());
System.out.println(uri);
}
private String parseUri(String requestString){
int index1,index2=0;
index1=requestString.indexOf(' ');
if(index1!=-1){
index2=requestString.indexOf(' ',index1+1);
}
if(index2>index1){
//POST /chapter17/index.html HTTP/1.1
//截取[)的内容,上述例子中截取内容为/chapter17/index.html
return requestString.substring(index1+1,index2);
}
return null;
}
public String getUri(){
return uri;
}
}
3.Response
package demon1;
import java.io.*;
public class Response {
private Request request;
private 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[1024];
FileInputStream fis=null;
try{
System.out.println(PropertiesConst.WEB_ROOT);
File file=new File(PropertiesConst.WEB_ROOT,request.getUri());
if(file.exists()){
fis = new FileInputStream(file);
int ch=fis.read(bytes,0,1024);
output.write("HTTP/1.1 200 OK\r\n\r\n".getBytes());
while(ch!=-1){
output.write(bytes,0,ch);
ch=fis.read(bytes,0,1024);
}
}else {
String errorMessge = "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(errorMessge.getBytes());
}
}catch (Exception e){
System.out.println(e.toString());
}finally {
if(fis!=null){
fis.close();
}
}
}
}
上述的代码是一个简单得web服务器,目前所实现得功能只能处理静态资源得访问,他的作用就是想用来说明servlet容器的运行原理是和他一样得,都是这么个大致的流程。
代码中设计到得问题注意事项:
1.绑定本地ip和端口号的时候,需要设置backlog的值,上述代码中给的是1(随便给的),这里解释一下?
https://www.cnblogs.com/qiumingcheng/p/9492962.html(转),内容详解此链接
2.在网络传输的过程中都是字节流,将其字符转成对应的字节去传送的。
最后附上HTTP请求报文和相应报文
请求报文:
例子:
响应报文
举例: