手写简易的WEB服务
环境:
- JDK 1.8
- Idea 工具
- 新建Java项目
前提需要具备的基础
- Socket
- IO
思路
写一个服务端即可,用浏览器做现成的客户端
- 启动Socket服务,循环接收浏览器的请求
- 接收请求之后,将流中的数据取出
- 判断目标是资源是否存在,若不存在,返回404页面
- 若存在,将目标资源通过输出流响应给客户端(浏览器)
需要使用到的类
- Server:开启Socket服务
- Request:封装请求,处理请求的业务
- Response:封装响应,处理响应的相关业务
- Test: 测试类
Server服务器中
public class SimpleHttpServer { //端口 private int port=8080; //IP就是本地 不需要配置 //接收请求的方法 public void receiving(){ try { //创建Socket服务 ServerSocket serverSocket = new ServerSocket(port); //循环接收 while (true){ //每次请求就会拿到Socket对象就是接收一个请求 Socket socket = serverSocket.accept(); //System.out.println(socket); //获取连接对象的输入流 InputStream inputStream = socket.getInputStream(); //创建request对象 SimpleHttpRequest simpleHttpRequest = new SimpleHttpRequest(inputStream); //解析请求 simpleHttpRequest.parse(); //获取连接对象的输出流 OutputStream outputStream = socket.getOutputStream(); //创建Response SimpleHttpResponse simpleHttpResponse = new SimpleHttpResponse(outputStream); //进行响应 simpleHttpResponse.sendRedirect(simpleHttpRequest.getUri()); } } catch (Exception e) { e.printStackTrace(); } } }
Request对象解析请求
public class SimpleHttpRequest { private InputStream inputStream; //返回请求头中的网页资源路径 private String uri; public SimpleHttpRequest(InputStream inputStream) { this.inputStream = inputStream; } //进行解析 public void parse() { try { byte[] bytes = new byte[1024]; inputStream.read(bytes); String request=new String(bytes); System.out.println(request); parseUri(request); } catch (Exception e) { e.printStackTrace(); } } //解析 public void parseUri(String request) { int index1 ,index2; //找到第一次的空格 index1 = request.indexOf(32); index2 = request.indexOf(32, index1 + 1); //截取中间的资源 uri = request.substring(index1 + 1, index2); System.out.println(uri); } public String getUri() { return this.uri; } }
Response对象进行对请求信息的响应
public class SimpleHttpResponse { private OutputStream outputStream; public SimpleHttpResponse(OutputStream outputStream) { this.outputStream = outputStream; } public void sendRedirect(String uri) { try { //获取项目目录再拼接路径 String path = System.getProperty("user.dir") + "/WebContent" + uri; //判断资源uri是否存在 File file = new File(path); if (!file.exists()) { //不存在返回404 String error = getResponseMessage("404", "404 File Not Found"); System.out.println(error); this.outputStream.write(error.getBytes()); } else { //存在就返回目标资源的数据 FileInputStream inputStream = new FileInputStream(file); byte[] bytes = new byte[(int) file.length()]; inputStream.read(bytes); String result = new String(bytes); String responseMessage = getResponseMessage("200", result); this.outputStream.write(responseMessage.getBytes()); } } catch (Exception e) { e.printStackTrace(); } } //响应的格式 public String getResponseMessage(String code, String message) { return "HTTP/1.1" + code + "\r\n" + "Content-type: text/html\r\n" + "Content-Length: " + message.length() + "\r\n" + "\r\n" + message; } }
测试服务
public static void main(String[] args) { SimpleHttpServer server = new SimpleHttpServer(); System.out.println("Server Startup Successfully"); server.receiving(); }
测试中的数据
-
Socket[addr=/0:0:0:0:0:0:0:1,port=51572,localport=8080] 整个port是浏览器提供的接口
-
浏览器发送的请求消息
GET /index.html HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
记录错误:
java.net.SocketException: Socket is not bound yet 创建服务时忘记把端口传入进去
记录新发现:
System.getProperty("user.dir") ==> 获取项目的路径 本次获取的 D:\..\SimpleWebServer
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端