Tomcat的http通信由connector模块完成。connector启动之后初始化线程用来监听指定端口(默认是8080),每次接受到连接会通过线程池产生socket线程处理通信。整个流程很清晰,这里指列出主要的代码。主要涉及到下面几个类:
Connector,Http11Protocol,JIoEndpoint,SocketWrapper,DefaultServerSocketFactory
1. server.xml中配置:
<Connector port="8090" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
2. 构造Http通信的connector
Connector构造时传入"HTTP/1.1",通过反射构造Http11Protocol
public Connector(String protocol) {
setProtocol(protocol);
Class<?> clazz = Class.forName(protocolHandlerClassName);
this.protocolHandler = (ProtocolHandler) clazz.newInstance();
}
public void setProtocol(String protocol) {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName(org.apache.coyote.http11.Http11Protocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName ("org.apache.coyote.ajp.AjpProtocol");
}
}
public Http11Protocol() {
endpoint = new JIoEndpoint();
}
3. 初始化监听socket
protected void startInternal() throws LifecycleException {
protocolHandler.init();
protocolHandler.start();
}
public void protocolHandler .init() throws Exception {
((JIoEndpoint)endpoint).setHandler(cHandler);
try {
//这里提供了socketFactory的扩展,可以载入第三方的socketFactory。
if (isSSLEnabled()) {
sslImplementation =
SSLImplementation.getInstance(sslImplementationName);
socketFactory = sslImplementation.getServerSocketFactory();
((JIoEndpoint)endpoint).setServerSocketFactory(socketFactory);
} else if (socketFactoryName != null) {
socketFactory = (ServerSocketFactory) Class.forName(socketFactoryName).newInstance();
((JIoEndpoint)endpoint).setServerSocketFactory(socketFactory);
}
} catch (Exception ex) {
log.error(sm.getString("http11protocol.socketfactory.initerror"),
ex);
throw ex;
}
endpoint.init();
}
public void endpoint .init()
throws Exception {
if (serverSocketFactory == null) {
serverSocketFactory = ServerSocketFactory.getDefault();
}
serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog());
}
4. 新建线程,启动监听
public void protocolHandler .start() throws Exception {
endpoint.start();
}
public void endpoint.start() throws Exception {
// Create worker collection
if (getExecutor() == null) {
createExecutor();
}
// Start acceptor threads
for (int i = 0; i < acceptorThreadCount; i++) {
Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
acceptorThread.start();
}
}
}
5. 处理新连接
Accept类的run中,每次监听到新连接会执行processSocket(socket),通过executor把新连接放到独立的线程中。然后执行SocketProcessor.run。
protected boolean processSocket(Socket socket) {
SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
getExecutor().execute(new SocketProcessor(wrapper));
return true;
}
public void SocketProcessor.run() {
if ( (state != SocketState.CLOSED) ) {
state = (status==null)?handler.process(socket):handler.process(socket,status);
}
}
handler在初始化时设置((JIoEndpoint)endpoint).setHandler(cHandler);
以上分析了从建立监听到处理新连接的过程。通信模块通过包org.apache.tomcat.util.net来实现,在类JIoEndpoint中通过interfaceHandler开放HTTP协议解析接口。HTTP协议解析会在后面的文章中分析。