HTTP协议的请求和响应学习
本篇作为学习servlet的前提,http协议是学习JavaWeb开发的基石,不深入了解http协议,就不能说掌握了JavaWeb开发。
HTTP协议有两个版本:HTTP1.0和HTTP1.1,那么有什么区别呢?
HTTP协议1.0中,客户端与web服务端建立连接之后,只能获得一个资源,如果还想获得资源,那么久得重新连接。
而HTTP1.1协议则是客户端和web服务端连接之后,在这个连接上可以进行多个资源的传输。
关于这个HTTP1.1和HTTP1.0协议的区别可以使用Telnet进行验证。如果在命令行窗口cmd中提示“Telnet”不是Windows命令,则需要从【控制面板】--->【程序】--->【打开或关闭Windows功能】中勾选【Telnet客户端】。(Telnet是微软自带的可进行远程连接的工具)
开始在cmd中输入“telnet 主机名 端口号”,如输入:“telnet localhost 8080”:
默认情况下,Telnet是你输一个字符,它就发一个字符,并且不回显,如果需要回显,必须在输入以上命令启动Telnet后,同时按下【Ctrl】+【}】打开回显,并且最好是在记事本中先敲好要访问的命令,再复制进cmd中。
现在我用Telnet来访问我的Tomcat服务器,在我Tomcat服务器的【webapps】目录下有一个web应用,web应用所在目录名为【telnetTest】,其下有一个test.html文件,内容为“long live sd”,现在我使用Telnet以HTTP1.0协议去访问(访问之前记得开启Tomcat服务器哦):
打开回显,并回车一次,并输入请求行和主机(主机一定要有,无值则默认为本机),会看到如下:
使用HTTP1.0协议则是服务器将请求的资源传输回客户端后立即将连接断开,而使用HTTP1.1协议的情景如下图所示:
可见,HTTP1.1在将资源回传给客户端之后,不会立即断开连接,也就是说在未超时的时间内,客户端还可以向服务器请求资源,因为这个连接还未断开!(说实话Telnet实在太难用,还是用HttpWatch观察比较好。。。)
当然现在基本都是HTTP1.1协议,HTTP1.0协议已经基本不用了。。。因此我们所说的HTTP协议通常都是指HTTP1.1协议。
=============================================================================
一个有关HTTP协议的小问题:
一个web页面中,假设有三个<img>标签,这三个<img>标签引用了图片,当客户端访问这个web页面时,客户端总共会向服务器发生几次HTTP请求?
答案是四次,第一次是请求HTML页面,服务器将HTML页面传给浏览器后,浏览器开始解析HTML页面中的内容,而每次解析到<img>标签时,又要根据该标签的图片引用地址重新向服务器请求图片资源。所以总共有四次HTTP请求。因此在web优化中最重要的是要减少客户端向服务器的http请求次数。
=============================================================================
首先来看HTTP协议的请求内容:
一个完整的HTTP请求包含了如下内容:一个请求行,若干消息头,和空格之后的实体内容,如下图:
请求行:请求行的最开始为请求方式,原来总共有七种,现在只剩下GET(默认)和POST两种方式,其中POST方式又只用于表单的安全提交,而其他一般都是以GET方式来进行请求。
GET和POST方式的区别主要表现在数据的传递上:
如果请求方式为GET方式,则可以在请求的URL地址后以“?”的形式带上交给服务器的数据,多个数据之间以“&”隔开,例如:
GET /mail/1.html?username=admin&password=123 HTTP/1.1
但GET方式后附带的数据是有限的,不能超过1K。
如果请求方式为POST方式,可以在请求的实体内容中装载数据,而这个数据的装载大小是无限制的。
常用的消息头有很多,下图是一个示例:
Accept: 用于告诉服务器,客户端所支持的数据类型(MIME类型)。
Accept-Charset: 用于告诉服务器,客户端所采用的码表。
Accept-Encoding: 用于告诉服务器,客户端所支持的数据压缩格式。
Accept-Language: 用于告诉服务器,客户端采用的语言环境(国际化)。
Host: 用于告诉服务器,客户端想访问服务器哪台主机。
If-Modified-Since: 用于告诉服务器,客户端对于资源的最后缓存时间。
Referer: 用于告诉服务器,客户端是从哪个页面去访问服务器的 (防盗链)。
User-Agent: 用于告诉服务器,客户端的机器环境(例如所使用的操作系统,浏览器版本号)。
Cookie:客户端通过这个头字段,可以带一些数据给服务器。
Connection:客户端通过这个头字段告诉服务器,请求完成后,是保持链接还是关闭链接。
补充:
UA-CPU:用于告诉服务器,客户端操作系统的平台。
上面的一些消息头中细节说明:
国际化,比如Google这样的面对全世界的网站,可以根据“Accept-Language”这个消息头来回送对应语言的网页。
防盗链,一些服务器的资源只允许在某个页面中点击来请求,而不允许别人在他们做的页面中挂个超链接来指向这个资源从而导致在他们网页上直接点击就能获取资源。当然针对这些盗链我们可以指向自己的网站首页进行示威(~~(╯﹏╰)b)
==========================================================================
现在,来看HTTP协议的响应内容:
同样,对于服务器端响应客户端的请求,也会将数据进行HTTP协议的封装,形成响应,一个完整的HTTP请求包含了如下内容:一个响应状态行,若干消息头,还有空行之后的实体内容。同请求类似,如下图:
状态行:状态行的开始是使用的HTTP协议版本,后面跟的是状态码,状态码通常可以分为5类,如下:
其中有常见的404(资源未找到),200(请求成功并完成响应),500(服务器出错),剩下的也是非常重要的:
302:(Move temporarily):服务器告诉客户端其并无所需的资源,要客户端从其他地方寻求(重定向),新的URL在Location响应头中给出。
307(Temporary Redirect):同302状态码。
304(Not Modified):指示客户端只需要从缓存中寻求之前获得的数据即可,无需再从服务器端重新请求数据。
常用的响应头也有很多,下图是一个示例:
Location:这个头通常配合302或307状态码使用,服务器使用这个头告诉浏览器去找谁。
Server:服务器通过这个头告诉浏览器,服务器的类型。
Content-Encoding: 服务器通过这个头告诉浏览器,数据的压缩格式(gzip)。
Content-Length:服务器通过这个头告诉浏览器,回送数据的长度。
Content-Language: 服务器所在系统采用的语言环境。
Content-Type: 服务器通过这个头告诉浏览器,回送数据的类型(MIME类型);同时也告诉客户端所采用的编码表。
Last-Modified: 服务器通过这个头告诉浏览器,数据的最后修改时间。
Refresh:服务器通过这个头告诉浏览器,多长时间定时刷新或定时转向其他页面。
Content-Disposition: 控制浏览器以下载方式打开回送的数据。
Transfer-Encoding: 服务器通过这个头告诉浏览器,数据是以块方式回送的。
ETag:以一个网页或资源来生成某种值,如果网页或资源发生变化,则ETag值也发生变化,用来控制缓存。
Expires:控制浏览器缓存数据的时间(-1或0,代表控制浏览器不要缓存),如果是具体时间值,则是告诉浏览器在这个时间之前只需去缓存寻取资源即可。
Cache-Control: no-cache ,控制浏览器不要缓存该资源
Pragma: no-cache ,控制浏览器不要缓存该资源
(以上三个头一起用,就可以控制所有的浏览器不要缓存数据)
上面的一些响应头中细节说明:
Content-Type:告诉客户端回送的数据类型,这个数据类型称为MIME类型;同时也告诉客户端所采用的编码表。
MIME类型根据实际文件的后缀名(即扩展名)来指定数据的样式写法,如为html文件,则对应的MIME类型为:“text/html”,如果是图片jpg文件,则对应的MIME类型为:“image/jpeg”等等。
各种不同文件对应的MIME类型可以从网上对应,也可以从Tomcat服务器的【conf】目录中的“web.xml”文件中查看。
Content-Disposition:如果将某个资源设置了这个头,那么这个资源会以下载方式打开,而Content-Disposition头的写法为:“attachment;filename=”+文件URI。
ETag根据资源的变化做出ETag值的修改,如果客户端访问发现服务器端资源ETag值与客户端缓存中的相同资源ETag值不同,那么客户端就要重新获取数据。其实功能和(请求头If-Modified-Since结合响应头Last-Modified)是相同的,只是ETag能做到毫秒值级别的判断,而后者只能在秒值之间。
为什么控制浏览器不要缓存会有Expires,Cache-Control,Pragma这三个头,这是因为各种浏览器对禁止缓存使用的头不一样,所以以上三个响应头一起使用就可以对付所有浏览器。
最后的补充:
HTTP请求头中的“Range”请求头,可以请求服务器只传输某个web资源的一部分,这个头可以用来实现断点续传功能(当然前提是服务器是否支持Range功能,通过Accept-Ranges响应头来说明)。Range请求头可以通过三种格式来设置要传输的字节范围:
①Range:bytes=1000-2000 (请求传输某个资源1000到2000字节的内容)
② Range:bytes=1000- (请求传输某个资源1000字节以后的内容)
③ Range:bytes=1000 (请求传输某个资源最后1000字节的内容)
而与此对应的则是HTTP响应头中的“Accept-Ranges”响应头,这个响应头说明了该web服务器是否支持Range功能。如果支持则向浏览器返回“Accept-Ranges:bytes”,如果不支持,则返回“Accept-Ranges: none”。
另外还有一个Content-Range响应头,这个响应头说明了返回该web资源的字节范围,如果服务器支持断点续传功能,那么如果续传成功,则自动返回这个响应头。例:Content-Range:1000-3000/5000