[Tomcat] 基于Coyote的HTTP 1.1协议连接器
1. 模块架构org.apache.coyote.http11包支持http1.1协议,内部分为三类:ARP、NIO、普通http,这里只对最基本的普通http(使用java的IO流,而非NIO流)作简单研究。
这个包主要有以下几个类:
[*]Http11Protocol,实现了ProtocolHandler接口
[*]Http11Processor,实现了ActionHook接口
[*]InternalInputBuffer,实现了InputBuffer接口
[*]InternalOutputBuffer,实现了OutputBuffer接口
[*]InputFilter和OutputFilter接口,具体的实现类在 org.apache.coyote.http11.filters 中。
架构图如下所示(转自王程斯的博客):
处理流程:
[*]JIOEndpoint起到一个连接池的作用,可以启动多个socket监听,一旦收到浏览器发来的请求后,把对应的socket对象通过process方法,传递给Http11ConnectionHandler,再交给Http11Processor
[*]Http11Processor内部有个InternalInputBuffer(图上未画出),InternalInputBuffer是真正对socket中包含的字节流进行处理的,它将字节转换为Request
[*]Request流经过滤器filters,最后到达实现了Adapter接口的容器,模块的工作就到此为止,回头继续处理下一个socket
2. 代码研究
[*]Http11Protocol
该类是http1.1协议的ProtocolHandler实现,主要包含了内部类Http11ConnectionHandler和Http11ConnectionHandler的实例对象,它的初始化代码和过程如下:
public Http11Protocol() {
endpoint = new JIoEndpoint(); //新建endpoint,启动若干socket server,监听服务器端口
cHandler = new Http11ConnectionHandler(this); //协议连接处理对象,用于对socket连接的处理
((JIoEndpoint) endpoint).setHandler(cHandler); //一旦endpoint接收到请求,会将对应socket实例传给cHandler.process方法进行处理
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
}
Http11ConnectionHandler内部类则继承了AbstractConnectionHandler,它主要实现了createProcessor方法,用于将Http11Processor应用于连接处理流程中。函数内新建了一个Http11Processor实例,并将该实例绑定到ConnectionHandler上。ConnectionHandler一旦接收到从endpoint发来的处理请求,使用对应的Processor对接收到的数据进行处理,形成Request对象。
2. Http11Processor
这个类的作用就是生成Request(当然本质上还是InternalInputBuffer完成的),交给实现了Adapter接口的容器。它有adapter、request、response、inputbuffer、outputbuffer等几个关键字段,还有很多和http 1.1协议有关的字段和方法,用于协议的解析(这里就不对解析过程进行分析了)。
这个类对socket对象依次做如下的处理:
1) 把socket的inputstream和outputstream分别与inputbuffer和outputbuffer关联起来
2) 通过inputBuffer.parseRequestLine() 和 inputBuffer.parseHeaders() 方法,解析socket字节流中的头字段,写到request中
3) 通过prepareRequest方法组装filter,用于处理http消息体
4) adapter.service(request, response) 把生成的request和response交给容器处理
5) 如果一切顺利,开始处理socket中的下一个请求(因为http1.1是支持持续连接的,所以一个socket中可能包含多个请求),循环回到第一步
6) 如果出错,则设置response的响应码,并终止循环
其中的prepareRequest方法,是用于准备inputbuffer的filter,主要包括一下几个过程:
1) 根据之前对http头字段的解析,分别检查protocol、method、expect、user-agent和MIMEheaders,此外还检查URI的格式
2) 准备加载filter
3) 如果有transfer-encoding这个头字段,则分别设置不同编码的filter
4) 校验content-length头字段
3. InternalInputBuffer
这个类的主要功能是:从socket中获取字节流,将字节读入一个缓冲区buf,然后从缓冲区逐个解析http请求头以及内容。
主要的字段有:
request:Request对象,从缓冲区中解析出的信息会写入request中
buf:缓冲区,从socket的inputstream读取的字节放入此缓冲区中
headers : MimeHeaders,保存以键值对出现的报头,也就是除去请求报文第一行之后的所有头部
主要的方法有:
parseRequestLine()
解析请求报头的第一行,形如:GET http://class/download.microtool.de:80/somedata.exe,包括请求方法(GET or POST)、协议(http)、URI。解析后,放入request中
parseHeader()
解析刚才parseRequestLine()之后的报头,由于RequestLine之后的报头都是以“:”分隔的键值对,因此每执行一次本方法,则在headers 中加入一个键值对,如果格式错误则返回false
endRequest()
结束一个request的处理,把多余的字节清空
nextRequest()
准备下一个request的处理,这个方法主要用来对所有的标记位和指针进行复位
fill()
从socket的inputstream中读出一定数量的字节,填充buf,在很多方法中都有用到。例如解析报头时,当发现buf已经读取完了,就调用fill重新填充buf,如果inputstream已经读完了,fill返回false。
4. InternalOutputBuffer
这个类是用来从response中读取信息,然后写入socket的outputstream中,返回给客户端的。里面的很多方法和InternalInputBuffer基本相似,有两个是专门用于处理Response的:nextRequest()和endRequest()。这两个函数的功能主要是在当前Request处理完并发出Response之后,跳转到下一个Request的处理或者结束处理。
3. org.apache.coyote.http11.upgrade
Apache在基于coyote的HTTP 1.1连接器实现模块中还实现了能够供基于HTTP 1.1的一些协议和在HTTP 1.1基础上进行操作的接口和实现,方便进行扩展。它主要有以下几个类:
[*]UpgradeInbound接口
接口定义了基于socket数据流处理需要实现的一些接口,主要功能是当连接器从socket中读取出数据后,会通知UpgradeInbound实现类进行数据解析,即onData函数。
2. UpgradeProcessor类
这个类是基于HTTP 1.1连接器的upgrade连接器Processor的模板类,定义了一个标准的UpgradeProcessor必须要重写的读写处理函数:
// Output methods
public abstract void flush() throws IOException;
public abstract void write(int b) throws IOException;
public abstract void write(byte[] b, int off, int len) throws IOException;
// Input methods
public abstract int read() throws IOException;
public abstract int read(boolean block, byte[] bytes, int off, int len)
throws IOException;
3. UpgradeOutbound类
该类继承了OutputStream类,重写了write函数。这个类是一个功能封装类,在类初始化的时候传入用于解析数据的UpgradeProcessor,而在重写的write函数中则直接调用Processor的处理函数,使得数据能够被写到Upgraded的数据流中。
参考材料:
http://blog.iyunv.com/wangchengsi/article/details/2995536
页:
[1]