tomcat Http11NioProtocol如何解析http请求及如何解决TCP拆包粘包

前言

tomcat是常用的Web 应用服务器,目前国内有很多文章讲解了tomcat架构,请求流程等,但是没有如何解析http请求及如何解决TCP粘包拆包,所以这篇文章的目的就是介绍这块内容,一下内容完全是个人查看tomcat nio 相关源码来总结的,源码版本9.0.30,欢迎提问,欢迎指出错误。

请求解析

参数在请求行时的请求形式

GET /myServlet?name=zhangsan HTTP/1.1
Connection: keep-alive

参数在请求体时的请求形式

POST /myServlet HTTP/1.1

Connection: keep-alive

 

name=zhangsan

中间有一个空行表示请求头和请求体的分界。

解析请求行

以 GET /myServlet?name=zhangsan HTTP/1.1为例

将请求行按空格进行分割,将method(POST),requestURI(/myServlet ),protocol(HTTP/1.1 )存起来

将?之后的数据存入queryString(name=zhangsan)存起来。

一直遇见换行符解析结束。

解析请求头

以这个为例

Content-Length: 13

Connection: keep-alive

 

name=zhangsan

解析过程很简单,以":"进行分割,一直到读取到一个只有换行符的空行,请求头解析结束。

解析请求体

请求体解析是通过请求头中的Content-Length来进行解析的,读取Content-Length值中对应的字节数。

如何解决拆包粘包

知道了请求结果和解析流程,下面就介绍一下怎样处理拆包粘包。

粘包

粘包的解决是非常简单的,比如粘包后是这样的数据。

POST /myServlet?name=liuhao HTTP/1.1

Content-Length: 13

 

name=zhangsan

POST /myServlet?name=liuhao HTTP/1.1

tomcat处理请求时根据Content-Length进行读取,是不会读到第二个请求的,如果没有Content-Length的话也就没有请求体,请求头和下一个请求有空行,也不会读取。

拆包

拆包的处理方式大致相同就是数据没有读取完成就等

请求行拆包

POST /myServlet?name=liuh

请求行拆包,请求行结束的标志是换行符,如果没有收到换行符,表示请求行没有解析完,这个时候会重新监听读事件(使用java nio selector),之前的数据会放到buffer中缓存。

请求头拆包

POST /myServlet?name=liuhao HTTP/1.1

Content-Type:

请求头拆包,请求头结束的标志是空行,如果没有只有换行符的空行,表示请求行没有解析完,这个时候会重新监听读事件(使用java nio selector),之前的数据会放到buffer中缓存。

请求体拆包

POST /myServlet HTTP/1.1

Content-Length: 13

Connection: keep-alive

 

name=

请求体拆包,请求体结束的标志是数据读取足够的字节数,如果读取不够,会阻塞的读取数据直到读取成功或超时报错。

源码阅读指南

将tomcat的源码导入到IDE,然后从架构和原理来了解tomcat,之后可以通过阅读其他博客来了解源码,最后自己在IDE中查看相关源码,如果看的吃力,可以debug来看,如果想看拆包解包的源码,可以用postman发送一个完整的http请求,然后使用telnet来进行拆包粘包测试,也可以写一个client来测试,不过有一点要注意,telnet每次回车时会将\n传过去,需要在debug的时候去除,如果写一个client的话也要注意这一点。

posted @ 2020-03-16 23:28  刘皓lh  阅读(2546)  评论(0编辑  收藏  举报