一,HTTP协议

  • HTTP请求的例子
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: www.baidu.com
Connection: Keep-Alive

请求正文

  • HTTP响应的例子
HTTP/1.1 200 OK
Date: Mon, 15 Dec 2014 07:53:11 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: Keep-Alive
Cache-Control: private
Expires: Mon, 15 Dec 2014 07:53:11 GMT
Server: BWS/1.1
BDPAGETYPE: 2
BDQID: 0xa963f5f000001f3e
BDUSERID: 347544430

响应正文




不管是http的请求还是响应的内容,从信息的角度看,都是一段文本(HTTP2.0的请求或响应就不是文本信息了,而是二进制信息)。这段文本的本质就是一系列的命令。这些命令组成一门语言或者是一个协议。而服务器和浏览器要做的事情就是具有解析这门语言或协议的能力。在这里,tomcat要解析的是http请求这门“语言”,浏览器要解析的是http响应这门“语言”。有人会想到,tomcat除了要解析http请求,还要返回http响应。但是tomcat组装http响应其实是纯字符串操作,并不需要复杂的逻辑。所以,要读tomcat的源码,第一个重点就是:tomcat是怎么解析http请求的。

这里我也谈谈我对协议的理解:协议对于制定者来说,是一组规则或者是一组命令;对于服务器的开发者来说,就是要他做一个解析这组命令的解析器;对于我们使用者来说,就是一门“语言”。比如在数学领域,四则运算是数学家发明出来的一组规则,老师教我们四则运算其实是把一个解析器植入我们的大脑,我们做算术题的时候,其实是把四则运算当成一门语言了,而这门语言可以解决很多现实问题。
 

二,Socket机制

有了协议之后,我们可以根据协议写一段信息,然后发送给服务器。但是通过什么途径,可以把一段信息给发出去呢?这里靠的是各系统或平台都支持的Socket机制。

伯克利版本的UNIX系统首先引入socket interface。Lunix,Windows,Java等系统或平台都支持socket interface。

Java中Socket关系图:

Socket1和Socket2其实是浏览器的,我们管不着。浏览器端的Socket组成一个队列,排着队试图和我们的Tomcat建立起TCP连接。我们Tomcat中有一个ServerSocket,每当等到一个来自浏览器建立连接的请求,就会new一个Socket出来(比如图中的Socket a和Socket b),和浏览器的那个Socket建立起联系。

ServerSocket是依据什么信息建立起来的呢?是IP和端口号。同一个主机的同一个端口号只能创建一个ServerSocket对象。

有些书上说ServerSocket是服务器端的套接字,Socket是客户端的套接字,其实是错误的。误导性很大。不管是浏览器还是tomcat,应该都有ServerSocket和Socket这两样东西,只不过可能叫法不一样。我理解ServerSocket是Socket的一个创建工厂。

Tomcat在和客户端建立连接的时候,只要调用几个接口就行了,所以这部分代码很少,算不上重点。但是对于理解tomcat的原理很重要



三,Servlet API

Servlet提供了一套面向web开发者的API。这些API是抽象的,并没有具体实现。实现这些API,当然也主要是tomcat的任务。在一个web应用中,web开发者只要实现Servlet接口,并把具体的Servlet配置在web.xml中。tomcat从web.xml中获取配置的servlet信息,然后通过反射机制实例化它。而这些Servlet需要的参数以及其他变量(Servlet API的一部分)都通过tomcat提供。

所以Tomcat的第二个重点是怎么实例化Servlet API。



四,Servlet容器

一个功能齐全的servlet容器要做的事:
1.当第一次调用某个servlet时,要载入该servlet类,并调用其init()方法(仅此一次);
2.针对每个request请求,创建一个javax.servlet.ServletRequest实例和一个javax.servlet.ServletResponse实例;
3.调用该servlet的service()方法,将ServletRequest和ServletResponse对象作为参数传入;
4.当关闭该Servlet类时,调用其destroy()方法,并卸载该servlet类。

Tomcat的Servlet容器叫做Catalina【英文意思是远程轰炸机】,主要由连接器(Connector)和容器(Container)两个模块组成。

由上面的分析,我们也可以看得到,Connector主要是解析HTTP请求,Container重要是实现Servlet API。所以Catalina自然也就是以这两个模块构成。


五,总结