http协议基础知识总结

协议特点
1、基于请求和响应
客户端向http服务器发起一次请求,服务器对请求做出响应,一来一回。
2、无连接
无连接是指在应用层无连接,限制每次连接只处理一次请求,也就是说客户发起请求,服务器做出响应。连接即终止。这么做的原因是http是基于互联网的。服务器可能同时面对数十万,百万的请求。由于请求具有瞬时性,突发性。网页浏览具有联想性等等。造成相邻两次请求之间的关系可能不大。如果采用长时间连接的方式,大部分的网络资源就会被空闲下来,造成浪费。所以讲http协议设计成, 请求时建立连接,响应时释放连接,以尽快将资源释放出来去服务其他客户端。
但是http/1.1又推崇长连接的方式,这个我们在下面讨论。
3、无状态
无状态是指http协议没有记忆能力,当一次请求完毕后,它并不会将这次的数据保存下来。
缺点:下次请求的数据与上次相关联的话,就得进行数据重传,可能会造成每次传输的数据量都很大。
优点:在不需要上次的数据时,应答比较快。
4、简单快速
协议简单,一来一回就结束(一次请求,一次应答),使得http服务器的程序规模小,不需要去处理太复杂的逻辑,因而通信速度很快。
5、灵活
http协议允许传输任意类型的数据,类型有报文头部的Content-Type指出。

总之,http协议的种种特点,都简化http服务器的设计,使其可以接受大量高并发的请求。


http协议既然是基于请求和响应的,那么就必须有请求和响应两种报文。

请求报文
http协议的请求报文包含三个部分,请求行,请求头部,空行,请求数据三部分构成。如下图:

我们可以明显看到一个特点,请求数据之上,每一行末尾都有一个回车换行,说明http协议报头是严格以行为单位的,切记这点。至于回车换行到底是两个字符"\r\n"还是一个字符"\r"或者"\n",这个不用去深究,不同系统下格式也有所不同。
千万要留意,请求头部与请求数据之间有一行空行。这个空行作为请求数据开始的标志,也作为请求头部结束的标志。

请求行
请求头部由三部分构成,每个部分以空格作为分隔符。
URL
我们先说第二部分URL。URL是一个统一资源标识符,标识着我们请求访问的主机和请求资源在服务器上的存放路径。它的格式如下:

http://host[":"port][abs_path][?name=value&name1=value1&...]

上面的是不是很眼熟,就是我们访问网页的网址,抛去“http://”剩下的部分就是报头中的URL。
1、host :指我们要访问的主机的IP或者域名。
2、port :指我们要访问的主机的端口,如果不写,默认为80端口。
3、abs_path:指我们请求的资源的路径。如果我们发送一个请求资源报文,至少指定abs_path为“/”,意为,请求web服务器根目录下的资源。现在浏览器一般都帮我们完成了这个工作。
4、[?name=value&name1=value1&...] :有时我们需要向服务器传递一些参数,这时就以问好“?”作为path和参数的分隔符,参数以name=value的形式给出,不同参数之间以取地址符“&”作为分隔符。不过仅限于GET方法的参数会在url中显示出。(会在下面分析)

下面看个例子:
我们在浏览器网页窗口输入“www.baidu.com”


当浏览器解析完毕后,自动为我们加上了根目录:


(https协议是http协议的一种加密版)

再看一个例子:
我们访问CSDN的知识库页面:


lib.csdn.net就是域名,后面的一堆就是资源路径。

第三个例子:
我们在平常浏览网页的时候,可能经常看到这样的网址。


以问好作为其实的后面的一堆,就是参数。

大家可能注意到,我在访问这两个网站的时候都没有加端口号,还是成功访问了,这就是默认了80端口。

请求方法

现在互联网上的资源多种多样,http的请求方法自然也有很多种。每一种都有不同的目的。
这里大家先分清楚两个概念:
  1. 静态页面请求,静态页面请求就是向服务器请求一张html页面,我只看看,别的不做。
  2. cgi请求:cgi请求是请求服务器的一个外部程序。比如久久时间网的计算时间功能,我们向服务器提交一些参数,服务器通过调用外部程序进行运算再将结果返还给我们。

GET:请求获取URL所标识的资源(是不是很好理解了),GET请求就有以上描述的两种请求方式之分。
  1. 不带参数的GET,为静态页面请求,就是我们平常的普通浏览页面。
  2. 带参数的GET,cgi请求。(参数会在url中显示出)

POST:与带参数的get方法用法相似,只要是post方法,就一定是cgi请求。post的参数放在报文第三部分请求数据中,参数的长度在报文第二部分的Content-Length给出。post方法常用于提交表单。
HEAD:请求获取由URL标识的资源的响应报文。
PUT:请求服务器存储一个资源,并用URL作为标识。
DELETE:请求服务器删除URL所标识的资源。
TRACE:请求服务器回送收到的请求消息,主要用于测试或诊断。
CONNECT:保留将来使用
OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项和需求。


请求协议

请求协议一般是HTTP/1.0,不过近年来开始流行HTTP/1.1。


请求头部
请求头部允许客户端向服务器传递请求的附加信息以及客户端自身的信息。
采用name:value的形式,以行为单位。
常用的请求头部如下:
Accept : 指定客户端接受那些类型的信息。如:Accept:text/html 表示客户端可接受html类型的文本数据。
Accept-Charset:指定客户端接受的字符集,如果没有明确指定,表示任何字符集都可接受。
Accept-Encoding:指定可接受的内容编码。
Accept-Language:指定一种自然语言
Authorization:用于验证客户端有权查看某个资源,当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。

下面看一个完整的请求报文。

POST /cgi/cgifun HTTP/1.1
Host: 192.168.3.21:8080
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20131029 Firefox/17.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://192.168.3.21:8080/
Content-Type: application/x-www-form-urlencoded
Content-Length: 65
空行
firstname=Mickey&firstname=Mickey&lastname=Mouse&firstname=Mickey(请求数据/POST的参数)




响应报文

同样响应报文格式和请求报文保持一致,只是内容有些改变。响应报文由响应行,响应头部,空行,响应数据四部分组成。
把请求报文的图照搬下来,名字变一下就是了。
响应报文与请求报文的最大不同点在于第一行,响应行。
响应行
响应行也是由三部分构成,协议版本,响应状态码,响应状态码文本描述。如下面这行数据:

HTTP/1.0 200 ok

响应状态码为200,表示成功响应,文本描述为OK。响应状态码有很多种。
1xx:表示请求已接受,继续处理
2xx:表示请求已被成功接受,理解,接受
3xx:重定向,要完成请求必须更进一步的操作。
4xx:客户端错误,请求有语法错误或请求无法实现。
5xx:服务端错误,服务器未能实现合法的请求。

常见的状态码有:(后面的英文是对应的文本描述)
200 OK      //客户端请求成功
400 Bad Request  //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden  //服务器收到请求,但是拒绝提供服务
404 Not Found  //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable  //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

响应头部
响应头部允许服务器传递不能放在状态行中的响应信息,以及关于服务器的信息和对于URL所标识的资源进行下一步访问的信息。
Location:响应报头域用于重定向接受者到一个新的位置。Location响应报头域常用在更换域名的时
Server:响应报头域包含了服务器用来处理请求的软件信息。与User-Agent请求报头域是相对应的。
WWW-Authenticate:响应报头域必须被包含在401(未授权的)响应消息中,客户端收到401响应消息时候,并发送Authorization报头域请求服务器对其进行验证时,服务端响应报头就包含该报头域。
eg:WWW-Authenticate:Basic realm="Basic Auth Test!"  //可以看出服务器对请求资源采用的是基本验证机制。

关于头部部分,除了上述所说的响应头部和请求头部之外还有以下几种常见属性。
普通头部
在普通头部中,有少数报头域用于所有的请求和响应消息,但不用于被传输的实体,只用于传输的消息。
Cache-Control:用于指定缓冲指令。缓存指令是单向的(响应中出现未必请求中也出现),独立的(一个消息中的缓存指令不会影响另一条消息)
请求时的缓存指令包括:no-cache(用于指示请求或响应消息不能缓存)、no-store、max-age、max-stale、min-fresh、only-if-cached;
响应时的缓存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage.


Date:普通报头域表示消息产生的日期和时间
Connection:普通报头域允许发送指定连接的选项。例如指定连接是连续,或者指定“close”选项,通知服务器,在响应完成后,关闭连接

实体头部
请求和响应消息都可以传送一个实体。一个实体由实体报头域和实体正文组成,但并不是说实体报头域和实体正文要在一起发送,可以只发送实体报头域。实体报头定义了关于实体正文(eg:有无实体正文)和请求所标识的资源的元信息。
常用的实体报头
Content-Encoding
Content-Encoding实体报头域被用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容的编码,因而要获得Content-Type报头域中所引用的媒体类型,必须采用相应的解码机制。Content-Encoding这样用于记录文档的压缩方法,eg:Content-Encoding:gzip
Content-Language
Content-Language实体报头域描述了资源所用的自然语言。没有设置该域则认为实体内容将提供给所有的语言阅读
者。eg:Content-Language:da
Content-Length
Content-Length实体报头域用于指明实体正文的长度,以字节方式存储的十进制数字来表示。
Content-Type
Content-Type实体报头域用语指明发送给接收者的实体正文的媒体类型。eg:
Content-Type:text/html;charset=ISO-8859-1
Content-Type:text/html;charset=GB2312
Last-Modified
Last-Modified实体报头域用于指示资源的最后修改日期和时间。
Expires
Expires实体报头域给出响应过期的日期和时间。为了让代理服务器或浏览器在一段时间以后更新缓存中(再次访问曾访问过的页面时,直接从缓存中加载,缩短响应时间和降低服务器负载)的页面,我们可以使用Expires实体报头域指定页面过期的时间。eg:Expires:Thu,15 Sep 2006 16:23:12 GMT
HTTP1.1的客户端和缓存必须将其他非法的日期格式(包括0)看作已经过期。eg:为了让浏览器不要缓存页面,我们也可以利用Expires实体报头域,设置为0,jsp中程序如下:response.setDateHeader("Expires","0");

以上关于报文头部的知识来自于 http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html



长连接与短连接

http协议在应用层是无连接的,但在传输层,它使用TCP协议,还是需要建立一定的连接。http的TCP连接有两种,长连接与短连接。

短连接
短连接指:一次连接只支持一次数据的发送或接受,当数据交互完毕后,立即关闭连接
客户端请求连接---服务端响应,建立连接(三次握手) --- 传输数据 --- 服务端关闭连接 (四次挥手)

短连接的好处:短连接逻辑简单,一来一回即关闭连接,这样可以加快服务器的处理速度,提高服务器的工作效率。一定程度上可以简化http服务器代码逻辑,使其变的更简单。


长连接
长连接:一次连接支持多次数据的交互,当没有数据的交互时,有心跳机制来维护持续的连接。
客户端请求连接---服务端响应,建立连接(三次握手) --- 传输数据 --- 心跳 --- 传输数据 --- 心跳 --- ... --- 关闭连接

长连接的好处:
1、可以减少TCP建立连接三次握手与释放连接四次挥手所造成开销,减少网络流量。
2、在连续的请求同一服务器时,可以降低网络延迟。在使用https时效果明显,可以减少SSL/TLS所造成的大量开销。(加密解密算法)
3、让TCP有足够的时间判断网络拥塞状况,方便下步操作。

长连接也有不好的地方:
1、容易被攻击,当恶意用户想服务器发起了多个长连接请求,但是不进行数据交互,那么在那一段时间内,服务器的大部分资源都被这些长连接占据,此时其他用户就无法访问该服务器。
2、当维持大量长连接是,服务器的压力会大大增大。


TIME-OUT与心跳机制
客户端发起的长连接不可能长时间占用服务器资源,一般在报文的头部中有个Keep-Alive选项会指明timeout时间或者指明max次数,一旦超过这个事件或一旦超过请求的max次数,这个连接就会自动断开。
当没有超过范围,并且在连接空闲情况下,客户端与服务器之间会以心跳包的方式来维护连接,每隔一段时间客户端或者服务器就会发出一个心跳检测包,如果对端给出了回应报文,则继续维护连接。否则断开连接。



在web开发中,http长连接与浏览器并发连接的数量限制也有一定的关系。
为什么要浏览器要有并发连接数的限制?
1、TCP协议的限制,PC端只有65536个端口可以向外部发出连接,而操作系统对半开连接数也有限制以保护操作系统的TCP/IP协议栈资源不被迅速耗尽。因此浏览器不好发出太多的TCP连接。而是采取连接复用(长连接)或者等一次连接完毕再重新建立连接的方式。(半开连接指的是 TCP 连接的一种状态,当客户端向服务器端发出一个 TCP 连接请求,在客户端还没收到服务器端的回应并发回一个确认的数据包时,这个 TCP 连接就是一个半开连接。若服务器到超时以后仍无响应,那么这个 TCP 连接就等于白费了,所以操作系统会本能的保护自己,限制 TCP 半开连接的总个数,以免有限的内核态内存空间被维护 TCP 连接所需的内存所浪费。)
2、 如果采用阻塞的套接字模型来建立连接,同时发出多个连接会导致浏览器不得不多开几个线程,而线程有时候算不得是轻量级资源,毕竟做一次上下文切换开销不小。
3、保护服务器,减小服务器的压力。还因为当一个强势的连接请求与一个弱势的连接请求同时访问服务器时,抢手者会一直占用服务器,导致弱势者无法访问公共资源。
为了迎合浏览器并发连接数的限制,长连接是一个很好的选择。

关于上面提到的浏览器的并发连接也可理解为一种http连接方式,称为并行连接。
并行连接
由于现代网页通常包含了复数个(>=10)资源,而按照默认设定,一个连接中的每一个请求必须等待收到响应后才能发送下一个请求,所以如果复数的资源请求全部在一个连接one by one发送给服务器显然会很慢,而为了弥补这一缺陷,浏览器通常会默认开启多个TCP连接,然后再根据每个连接的状态在其中依次发送数据请求,而且客户端有权任意关闭超发的连接。各个浏览器允许的并行连接数大致是这样的(From SO):
Firefox 2:   2
Firefox 3+:  6
Opera 9.26:  4
Opera 12:   6
Safari 3:   4
Safari 5:   6
    IE 7:       2
    IE 8:       6
    IE 10:      8
    Chrome:      6

由于TCP协议本身有慢启动的特征,会随着时间调谐连接的最大速度,因此在现代浏览器中持久连接和并行连接通常是搭配在一起使用的—— 一方面由于持久连接的存在,每个TCP连接已经处于调谐后的状态,另一方面持久连接可以避免重新三次握手的开销。

管道持久化连接
按照HTTP1.1的描述,还有种可以提升性能的方案是管道化,可以在一个连接中发送多个请求不必等待前一个请求返回。但这项技术比较容易踩坑,所以主流面向用户的浏览器,这项技术是被默认关闭。管道化的具体情形如下图:


  • 40
    点赞
  • 219
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值