1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

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-bootflag先立起来。

服务端

服务端其实就是一个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的封装。我们根据这个也可以大胆推测,tomcatRequestResponse也是类似的实现。

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

这不就是浏览器的请求头吗?里面包括了请求地址、以及客户端的其他信息。

如果你想实现更加请求地址响应的需求,只需要解析下请求数据就行了,我觉得这些都简单了,最难的是从01,就是浏览器可以请求后可以收到响应,我觉得我现在做到了0.5,后面的0.5还需要再研究下。

总结

整体来说,这个实例还是比较简单的,虽然最后没有完整地达到了最终的目的,但是还是有收获的,至少服务请求收到了吧,所以从这个点上将,收获还是大于预期的,而且对我而言还发现新大陆,只要这个缺憾,后面再好好摸索下,反正这个硬砍我啃定了。

posted @   云中志  阅读(102)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示