2021.05.28 手写简易web服务器
作者:@syske
本文为作者原创,转载请注明出处:https://www.cnblogs.com/caoleiCoding/p/14826011.html
前言
已经做java
开发好几年了,但是一直觉得web
服务器是个很神秘的东西,之前有参考过一个大佬用netty
写的简易版的springboot
,但是最后不了了之了。今天,突然又有了想写个web
服务器了,所以就有了今天个小demo
。
但是demo
还是有点问题,就是浏览器请求的时候,服务端无法响应,但是把浏览器请求终止掉,服务端开始响应了,但是这时候响应结果已经无法传给浏览器了。这个问题,后期得研究下。
开整
今天才真正知道并理解了Tomcat
是基于socket
实现的,以前可能看到过相关博客和文档,但是一直无法正在理解,想不明白它到底是咋样通过Socket
实现的,直到今天写完这个demo
,我发现突然就想明白了,顿悟的感觉,所以我已经决定自己要动手写一个web
框架,名字就叫syske-boot
,flag
先立起来。
服务端
服务端其实就是一个socket
服务端,用于处理客户端请求。
public class SyskeCatServer { private static final int port = 8080; public static void main(String[] args) throws Exception{ ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); System.out.println("SyskeCatServer is starting……"); while (true){ Socket accept = serverSocket.accept(); InputStream inputStream = accept.getInputStream(); OutputStream outputStream = accept.getOutputStream(); SimpleHttpServer simpleHttpServer = new SimpleHttpServer(); SyskeRequest syskeRequest = new SyskeRequest(inputStream); SyskeResponse syskeResponse = new SyskeResponse(outputStream); simpleHttpServer.doService(syskeRequest, syskeResponse); accept.close(); } } catch (Exception e) { e.printStackTrace(); } finally { serverSocket.close(); } } }
首先,从serverSocket
中分别获取输入流和输出流,这里的SyskeRequest
就是对InputStream
的封装,SyskeResponse
就是对OutputStream
的封装。我们根据这个也可以大胆推测,tomcat
的Request
和Response
也是类似的实现。
doService方法
class SimpleHttpServer { public void doService(SyskeRequest request, SyskeResponse response) throws Exception { try { byte[] bytes = new byte[1024]; int read; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); while ((read = request.getInputStream().read(bytes)) != -1) { byteArrayOutputStream.write(bytes); } byte[] toByteArray = byteArrayOutputStream.toByteArray(); String requestStr = new String(toByteArray); System.out.println(String.format("请求参数:%s", requestStr)); String[] split = requestStr.split("\r\n"); System.out.println("end"); response.write("hello syskeCat"); } catch (Exception e) { e.printStackTrace(); } } }
SyskeRequest
这里就是包装了InputStream
public class SyskeRequest { private InputStream inputStream; public InputStream getInputStream() { return inputStream; } public SyskeRequest(InputStream inputStream) { this.inputStream = inputStream; } }
SyskeResponse
这里就是对OutputStream
简单包装
public class SyskeResponse { private OutputStream outputStream; public SyskeResponse(OutputStream outputStream) { this.outputStream = outputStream; } //将文本转换为字节流 public void write(String content) throws IOException { StringBuffer httpResponse = new StringBuffer(); httpResponse.append("HTTP/1.1 200 OK\n") //按照HTTP响应报文的格式写入 .append("Content-Type:text/html\n") .append("\r\n") .append("<html><head><link rel=\"icon\" href=\"data:;base64,=\"></head><body>") .append(content) //将页面内容写入 .append("</body></html>"); outputStream.write(httpResponse.toString().getBytes()); //将文本转为字节流 outputStream.close(); } }
测试
好了,上面这些就是核心代码了,是不是很简单。我们来运行下看看,直接运行main
方法就行了。服务端启动了:
浏览器访问下看看:
这里浏览器一直没响应,但是后台也没有收到请求,但是当我终止请求后(点击浏览器的x
),服务端收到了请求:
看下后端收到的socket
请求参数,是不是很熟悉:
请求参数:GET /tfgdfgdf HTTP/1.1 Host: localhost:8080 Connection: keep-alive Cache-Control: max-age=0 sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90" sec-ch-ua-mobile: ?0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: NMTID=00O3GJZgJXpkp8vI0cpmNRliUnGvYkAAAF4sPsi2w
这不就是浏览器的请求头吗?里面包括了请求地址、以及客户端的其他信息。
如果你想实现更加请求地址响应的需求,只需要解析下请求数据就行了,我觉得这些都简单了,最难的是从0
到1
,就是浏览器可以请求后可以收到响应,我觉得我现在做到了0.5
,后面的0.5
还需要再研究下。
总结
整体来说,这个实例还是比较简单的,虽然最后没有完整地达到了最终的目的,但是还是有收获的,至少服务请求收到了吧,所以从这个点上将,收获还是大于预期的,而且对我而言还发现新大陆,只要这个缺憾,后面再好好摸索下,反正这个硬砍我啃定了。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步