首先需要了解HTTP请求和响应
1.1 HTTP请求
一个HTTP请求包含3个部分:
- 请求方法(GET/POST/DELETE等) 统一资源标识符(URI) 协议/版本(HTTP/1.1)
- 请求头(Key-value)
- 实体
1.2 HTTP响应
一个HTTP响应也包含3个部分
- 协议(HTTP/1.1) 状态码(200/404/500等) 描述(OK)
- 响应头(K-V)
- 响应实体段
2.1 Java网络编程的两个类
Java中的网络编程主要用到的类有Socket(客户端)和ServerSocket(服务端)两个。
客户端主要是通过Socket向服务端发送请求。
服务端主要是在监听客户端发送的请求并处理请求,因此服务端需要一值保持监听状态。服务端从来不会主动向客户端发送请求。
3.1应用程序实现
主要有3个类:
Request 客户端
Response 服务端
HttpServer 主程序
package ex01.lqp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Created by lqp
* Date: 2019/6/12
*/
public class Request {
private InputStream input;
private String uri;
public Request(InputStream input)
{
this.input = input;
}
public void parse(){
//从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(request.toString());
uri = parseUri(request.toString());
}
public 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 uri;
}
}
package ex01.lqp;
import java.io.*;
/**
* Created by lqp
* Date: 2019/6/12
*/
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,ch);
ch = fis.read(bytes,0,BUFFER_SIZE);
}
}
else{
//file not find
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){
System.out.println(e.toString());
}
finally {
if(fis!=null)
{
fis.close();
}
}
}
}
package ex01.lqp;
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;
/**
* Created by lqp
* Date: 2019/6/12
*/
public class HttpServer {
public static final String WEB_ROOT = System.getProperty("user.dir")+ File.separator+"webroot";
//shutdown command
private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
//the shutdown command recived
private boolean shutdown = false;
public static void main(String[] args)
{
HttpServer server = new HttpServer();
server.await();
}
public void await()
{
ServerSocket serverSocket = null;
int port = 8080;
try{
serverSocket = new ServerSocket(port,1, InetAddress.getByName("127.0.0.1"));
}catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
//Loop waiting for a request
while(!shutdown)
{
Socket socket = null;
InputStream input=null;
OutputStream output = null;
try{
socket = serverSocket.accept();
input = socket.getInputStream();
output = socket.getOutputStream();
//创建Request对象并解析
Request request = new Request(input);
request.parse();
//创建Response对象
Response response = new Response(output);
response.setRequest(request);
response.sendStaticResource();
socket.close();
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
}catch (Exception e)
{
e.printStackTrace();
continue;
}
}
}
}
运行程序:
启动Main函数后,在浏览器中输入:
http://localhost:8080/filename 即可在控制台看到请求以及响应。
该程序通过 SHUTDOWN命令关闭,因此在浏览器中输入一下地址即可关闭程序:
http://localhost:8080/SHUTDOWN