您的位置:首页 > 理论基础 > 计算机网络

一个HTTP请求引发的问题

2015-03-01 00:39 253 查看
一直在搬代码,知道怎么写jsp,怎么写servlet,怎么运行tomcat,但是对这其中的请求过程往往就忽略了。相信大多数的初级程序员都是和我一样的,平时只知道搬代码而忽略了请求的过程问题。用了一个下午捋顺了一下,对tomcat的一个HTTP请求的过程。

首先,先说一下HTTP协议,HTTP协议也就是超文本传输协议,是一个关于如何在网络 上传输超级文本(HTML)的协议。在分层的计算机网络体系中HTTP位于应用层,建立在TCP/IP协议的基础上,HTTP靠的是可靠的TCP链接,默认的端口是80端口。HTTP协议规定web的基本运作过程基于客户/服务器通信模式。一个通信连接建立的过程如下:

1. 客户端与服务器端建立TCP连接。

2. 客户端发出HTTP请求。

3. 服务端返回响应的HTTP请求。

4. 客户端和服务器端的TCP连接关闭。

至于TCP连接是怎么建立的这里就不说了,好像是三次握手来着。用一个例子来说明,假设访问URL地址为http://www.inspur.com/news/index.htm的链接。具体的通信过程如下:

1. 浏览器与www.inspur.com服务器建立TCP连接。

2. 浏览器发出news/index.htm的HTTP请求。

3. web服务器在接收到请求之后解析HTTP请求返回包含index.htm数据的HTTP响应

4. 浏览器解析HTTP响应并显示

5. 浏览器与web服务器之间的TCP链接关闭。

这里需要说明的是在HTML文本中如果包含有图片,js,css等资源的时候,在浏览器解析HTML文件的时候会重新发起一个HTTP请求去请求图片资源。

接下来说一下HTTP请求的请求格式:

1.请求方法、URL和HTTP的协议版本。如:GET / HTTP/1.1

GET 完整请求一个资源,参数会显示在标题栏中。

POST:常用的提交表单方式,可以传输大量的数据。

HEAD:请求响应的首部。

DELETE:删除远程服务器上的文档。

PUT:上传文档到服务器。

2. 请求头。如:

Accept: / 就是告诉服务器端,我接受那些MIME类型

Accept-Language: zh-cn 告诉服务器能够发送哪些语言

Accept-Encoding: gzip, deflate 这个看起来是接受那些压缩方式的文件

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022) 用户代理,一般情况是浏览器

Host: www.google.cn 用来标识请求服务器上的那个虚拟主机

Connection: Keep-Alive

3. 请求正文,请求正文和请求头之间需要用空行分隔。请求体中可以包含大量信息。

HTTP响应的响应格式

1. HTTP协议的版本、状态吗、描述。如:HTTP/1.1 200 OK 三者之间用空格分隔。

2. 响应头。包含服务器类型、正文类型、正文长度等信息。如

Date: Fri, 22 May 2009 06:07:21 GMT

Content-Type: text/html; charset=UTF-8

3. 响应正文。响应正文就是服务器返回的具体信息。通常是HTML文档。

什么事MIME类型?

MIME(Multipurpose Internet Mail Extesions 多用途互联网邮件扩展)是一个互联网标准。在请求和响应中的文件(数据)类型,通常都是通过MIME类型进行指定的。在请求和响应中都有一个ContentType项指定请求或者响应正文部分的MIME类型。如:上传文档时的request请求的MIME类型为multipart/form-data,而在表单提交时的MIME类型则是默认的application/x-www-form-urlencoded 服务器端会根据不同的MIME类型进行不同的处理。同时在响应端也是如此。会根据正文的不同类型做出不同为响应。

在分析过一个HTTP请求之后,我们来看一下通常服务器端的响应,我们拿Tomcat和JSP来进行举例说明,在web的发展过程中,我们经历了从静态页面到动态页面的发展历程。

所谓静态文档就是事先存放在web服务器中的html文档,当请求web服务器时,服务器找到此文档并且返回该文档。这个阶段的HTML文件只能包含文本以及图片。

动态文档,就是在请求之前并不存在而是在请求过程中动态生成的响应。这一阶段用到了CGI程序和Servlet程序。

静态文档就没什么好说的了,主要说一下动态的响应的产生和发送。

如果想知道动态的响应产生,那么就要先说一下web容器,这里我们简单的说一下tomcat容器。

先说一下tomcat的简单构成,用个tomcat的程序狗应该都知道tomcat有一个server.xml里面配置了一些标签。

Server:代表了整个容器

Service: 是这样一个集合:它由一个或者多个Connector组成,以及一个Engine,负责处理所有Connector所获得的客户请求.

Connector:

一个Connector将在某个指定端口上侦听客户请求,并将获得的请求交给Engine来处理,从Engine处获得回应并返回客户

TOMCAT有两个典型的Connector,一个直接侦听来自browser的http请求,一个侦听来自其它WebServer的请求

Coyote Http/1.1 Connector 在端口8080处侦听来自客户browser的http请求

Coyote JK2 Connector 在端口8009处侦听来自其它WebServer(Apache)的servlet/jsp代理请求

Engine:Engine下可以配置多个虚拟主机Virtual Host,每个虚拟主机都有一个域名

当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理

Engine有一个默认虚拟主机,当请求无法匹配到任何一个Host上的时候,将交给该默认Host来处理

Host:代表一个Virtual Host,虚拟主机,每个虚拟主机和某个网络域名Domain Name相匹配每个虚拟主机下都可以部署(deploy)一个或者多个Web App,每个Web App对应于一个Context,有一个Context path当Host获得一个请求时,将把该请求匹配到某个Context上,然后把该请求交给该Context来处理匹配的方法是“最长匹配”,所以一个path==”“的Context将成为该Host的默认Context所有无法和其它Context的路径名匹配的请求都将最终和该默认Context匹配。

Context:

一个Context对应于一个Web Application,一个Web Application由一个或者多个Servlet组成

Context在创建的时候将根据配置文件CATALINAHOME/conf/web.xml和CATALINA_HOME/conf/web.xml和WEBAPP_HOME/WEB-INF/web.xml载入Servlet类,当Context获得请求时,将在自己的映射表(mapping table)中寻找相匹配的Servlet类.如果找到,则执行该类,获得请求的回应,并返回。

下面是tomcat的响应图示:



需要说明的是一个Context对应一个web app 。一个项目中可能包含多个servlet。

当一个Web App被初始化的时候,它将用自己的ClassLoader对象载入“部署配置文件web.xml”中定义的每个servlet类

它首先载入在$CATALINA_HOME/conf/web.xml中部署的servlet类

然后载入在自己的Web App根目录下的WEB-INF/web.xml中部署的servlet类

web.xml文件有两部分:servlet类定义和servlet映射定义

每个被载入的servlet类都有一个名字,且被填入该Context的映射表(mapping table)中,和某种URL PATTERN对应

当该Context获得请求时,将查询mapping table,找到被请求的servlet,并执行以获得请求回应

分析一下所有的Context共享的web.xml文件,在其中定义的servlet被所有的Web App载入。

下面举一个例子来简要说明一下这一过程:

假设来自客户的请求为:

http://localhost:8080/inspur/index.jsp

请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得

Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应

Engine获得请求localhost/inspur/index.jsp,匹配它所拥有的所有虚拟主机Host

Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)

localhost Host获得请求/inspur/index.jsp,匹配它所拥有的所有Context

Host匹配到路径为/inspur的Context(如果匹配不到就把该请求交给路径名为”“的Context去处理)

path=”/inspur”的Context获得请求/index.jsp,在它的mapping table中寻找对应的servlet

Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类

构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法

Context把执行完了之后的HttpServletResponse对象返回给Host

Host把HttpServletResponse对象返回给Engine

Engine把HttpServletResponse对象返回给Connector

Connector把HttpServletResponse对象返回给客户browser

这里可能有一个疑问,如果没有请求的servlet mapping会怎么样?其实请求jsp文件和servlet文件是一样的。在请求道jsp时,jsp会简单的处理此文件,把此文件转化为.java文件,其实很简单,原本的HTML内容转化为out.println(),而jsp中内嵌的java程序原封不动的保留,然后经过servlet容器进行编译,编译成servlet类,这样在执行完servlet类之后会返回响应对象,这样就和上面的过程相一致了。通常servlet类只会加载一次,因为一般的servlet的运行模式都是单例多线程运行。(虽然节省了内存,提高了响应时间。但这样会导致一些安全性的问题)。关于servlet的安全性问题以后有时间再深入学习一下。简单的HTTP请求过程我理解的大概就是这样,以后计划深入学习一下tomcat的一些内置对象,上面总结的如果有错误的地方还请批评改正,希望我们能一同进步。

特别感谢两篇博客: /article/5602746.html

/article/9656995.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: