InternalInputBuffer处理HTTP请求行

我们到底能走多远系列(11)

扯淡:

  最近行情不好吗?跳槽的比较少嘛,哈哈。有些人一直抗拒跳槽,觉得弊端很多:什么业务积累,职务,别人觉得你不可靠啊等等。我就想:这一辈子时间有限,何必为了一颗可以乘凉的树,放弃穿过森林的机会呢?祝在跳槽路上的朋友 顺利!(ps:个人喜欢面试 那种刺激感)

  最爽不顾躺着,最美不过夕阳。秋天的夕阳是一年中最华丽的,各位不要错过哦。

主题:

  在tomcat中,一个http请求,会被送到Http11Processor类,网站空间,执行这个类的process(Socket theSocket) 处理的传入的Socket,Socket里面装的就是http消息。

  tomcat是如何调用到Http11Processor的process方法的,可以参照:

  Http11Processor在org.apache.coyote.http11包下。

  Http11Processor的rocess方法中,用inputBuffer.parseRequestLine();调用了解析http消息的请求行。这里的inputBuffer是tomcat自定义的InternalInputBuffer。

  需要了解的是:

  1,服务器空间,org.apache.coyote.Request 是tomcat内部使用用于存放关于request消息的数据结构

  2,org.apache.tomcat.util.buf.MessageBytes 用于存放消息,在org.apache.coyote.Request中大量用于存放解析后的byte字符

  3,org.apache.tomcat.util.buf.ByteChunk 真正用于存放数据的数据结构,香港空间,存放的是byte[],org.apache.tomcat.util.buf.MessageBytes使用它。

  大流程:

  http消息通过inputBuffer解析后放到Request中,Request把它放到相应的MessageBytes,最后MessageBytes把它存到ByteChunk里。

  以上都可以通过方法调用来完成流程。

  主要关注的是解析的源代码,在查看源代码前需要了解http请求行的结构:可以参照:

  阅读前准备:

  1,方法中全部的异常时,会调用getString方法,其实就是StringManager的写日志方法,这是tomcat中统一的管理日志的方法。详细的解释在前一篇中已经几时过了:Tomcat StringManager阅读学习

  2,

源码:

  

public void parseRequestLine()throws IOException {int start = 0;//// Skipping blank lines// 忽略空行//byte chr = 0;do {(pos >= lastValid) {if (!fill())throw new EOFException(sm.getString(“iib.eof.error”));}chr = buf[pos++];} while ((chr == Constants.CR) || (chr == Constants.LF));pos–;// Mark the current buffer positionstart = pos;//// Reading the method name// Method name is always US-ASCIIspace = false;while (!space) {(pos >= lastValid) {if (!fill())throw new EOFException(sm.getString(“iib.eof.error”));}(buf[pos] == Constants.CR || buf[pos] == Constants.LF) {throw new IllegalArgumentException(sm.getString(“iib.invalidmethod”));}// Spec says single SP but it also says be tolerant of HT(buf[pos] == Constants.SP || buf[pos] == Constants.HT) {space = true;//跳出循环// 把下标记录下来,这里的method()得到一个Requast的MessageBytes:methodMBrequest.method().setBytes(buf, start, pos – start);}pos++;}// Spec says single SP but also says be tolerant of multiple and/or HT (space) {(pos >= lastValid) {if (!fill())throw new EOFException(sm.getString(“iib.eof.error”));}if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {pos++;// 忽略的方式就是继续移动下标} else {space = false;}}// Mark the current buffer positionstart = pos; end = 0;int questionPos = -1;//// Reading the URI// 上面是源码的注释,URI是什么?你懂的//boolean eol = false;while (!space) {(pos >= lastValid) {if (!fill())throw new EOFException(sm.getString(“iib.eof.error”));}// Spec says single SP but it also says be tolerant of HT(buf[pos] == Constants.SP || buf[pos] == Constants.HT) {space = true;end = pos;} else if ((buf[pos] == Constants.CR)|| (buf[pos] == Constants.LF)) {// HTTP/0.9 style request// 为了兼容HTTP/0.9格式eol = true;space = true;end = pos;} && (questionPos == -1)) {// 把问号的位置先记录下来questionPos = pos;}pos++;}// 把可能包含问号的URI的起始位和结束位记录下来request.unparsedURI().setBytes(buf, start, end – start);if (questionPos >= 0) {// 有问号的情况// 问号位置记录request.queryString().setBytes(buf, questionPos + 1,end – questionPos – 1);// 把URI记录下来request.requestURI().setBytes(buf, start, questionPos – start);} else {request.requestURI().setBytes(buf, start, end – start);}// Spec says single SP but also says be tolerant of multiple and/or HT (space) {(pos >= lastValid) {if (!fill())throw new EOFException(sm.getString(“iib.eof.error”));}if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {pos++;} else {space = false;}}// Mark the current buffer positionstart = pos;end = 0;//// Reading the protocol// Protocol is always US-ASCII//// eol标志位是为了标记是否是HTTP/0.9 style request 前面代码已经提到(!eol) {(pos >= lastValid) {if (!fill())throw new EOFException(sm.getString(“iib.eof.error”));}(buf[pos] == Constants.CR) {end = pos;} else if (buf[pos] == Constants.LF) {if (end == 0)end = pos;eol = true;}pos++;}((end – start) > 0) {request.protocol().setBytes(buf, start, end – start);} else {request.protocol().setString(“”);}}

总结习点:

  1,利用表示位来控制解析式每个while的功能,上面代码用的是space

  2,不用截断的方式存储需要的内容,而是记录开始和结束的下标。

让我们继续前行

———————————————————————-

努力不一定成功,但不努力肯定不会成功。共勉

重新开始吧!下次我会吸取教训,不让自己犯同样的错误的;

InternalInputBuffer处理HTTP请求行

相关文章:

你感兴趣的文章:

标签云: