HTTP的报文结构
HTTP有两类报文结构
- 请求报文-从客户端向服务器发送请求报文
-
响应报文 - 从服务器到客户端的回答
如下图是请求报文和响应报文结构图
image.png
image.png
HTTP请求报文和响应报文都是由三部分组成的,可以看出这两种报文的格式区别是开始行不同
- 开始行:
用于区分是请求报文还是响应报文,在请求报文中的开始行叫做'请求行',在响应报文中的开始行叫做状态行
,在开始行的三个字段之间都用空格分开 - 首部行
用来说明浏览器,服务器或报文主体的一些信息。首部可以有好几行,但也可以不使用。在每一个首部行中都有首部字段名和它的值,每一行在结束的地方都要有回车和换行,整个首部行结束时,还有一空行将首部行和后面的主体实体分开。 - 实体主体
在请求报文中一般都不用这个字段,而在响应报文中也可能没有这个字段
请求报文的方法
所谓方法
就是对请求的对象进行的操作,这些方法实际上也就是一些命令。因此请求报文的类型是由它所采用的方法决定的。
常用方法:
- option:请求一些选项的信息
- get :请求读取由URL所标志的信息
- head:请求读取URL所标志的信息的头部
- post:给服务器添加信息(例如:注释)
- put:在指明的url下存储一个文档
- delete:删除指明的url所标志的资源
- trace:用来进行环回测试的请求报文
- connect:用于代理服务器
请求报文举例
POST /somedir/page.html HTTP/1.1
//请求行 方法名 URL HTTP版本
Host: www.user.com
Content-Type: application/x-www-form-urlencoded
Connection: keep-Alive
User-agent: Mozilla/5.0
Accept-lauguage: fr
//以上是首部行
name = world //请求体
Host
:指明了该对象所在的主机
Connection
:Keep-Alive
首部行用来表明该浏览器告诉服务器使用持续连接
Content-Type
:x-www-form-urlencoded
用来表明HTTP会将请求参数用key1=val1&key2=val2 的方式进行组织,并放到请求实体里面
User-agent
:用来指明用户代理,即向服务器发送请求的浏览器类型
Accept-lauguage
:表示用户想得到该对象的语法版本(如果服务器中有这样的对象的话),否则,服务器应发送它的默认版本
响应报文举例
//状态行,协议版本 状态码 状态信息描述
HTTP/1.1 200 OK
//以下是首部行
Connection:close
Server:Apache/2.2.3(CentOS)
Date: Sat, 31Dec 2005 23:59:59 GMT
Content-Type: text/html
Content-Length: 122
//空行 分割header和实体主体
(data data data data) //响应实体主体
常见的状态短语
- 200 OK:请求成功,信息在返回的报文中
- 301:请求的对象已经被永久转移了,新的URL定义在响应报文中的Location:首部行中。客户软件将自动获取新的URL
- 400 :一个通用差错代码,指示该请求不能被服务器理解
- 404:被请求的文件不在服务器上
- 505:服务器不支持请求报文使用HTTP协议版本
Connection
:close首部行告诉客户,发送完报文后将关闭tcp连接
Date
:指的不是对象创建或最后修改的时间,而是服务器从文件系统中检索到该对象,插入到响应报文,并发送该响应报文的时间
Server
:该报文是由一台Apache Web
服务器产生的,类似于HTTP请求报文里的User-agent
Content-Length
:指示了被发送对象中的字节数
Content-Type
:指示了实体中的对象是HTML文本
get 和post 的区别
- get的请求参数一般以
?
分割拼接到URL后面,POST请求参数在body里面 - get参数长度限制为2048个字符,POST一般是没限制的
- get请求由于参数裸露在URL中,是不安全的,post请求则是相对安全。之所以是相对安全,是因为即使post参数非明文,但如果被抓包,都是不安全的。
从获取资源来说:
- get 获取资源是 安全的 幂等的(只读的,纯粹的),可缓存
- post 获取资源是不安全的,非幂等的,不可缓存的
- 这里的安全是指不会引起server端的任何状态变化
get的语义就是获取数据,是不会引起服务端状态的变化的,即是安全的 - 幂等:同一个请求方法执行多次和执行一次的效果完全相同,显然get 的请求是幂等,而post 是非幂等
这里用幂等形容get还不够,因为get不止是执行多次和执行一次的效果完全相同,而且执行一次和执行0次的效果也完全相同 - 可缓存:请求是否可以被缓存,get 请求会主动进行cache
因为get是幂等的,只读的,即get请求除了返回数据不会有其他副作用,所以get才是安全的,从而可以直接由cdn缓存,大大减轻服务器的负担,也就是可缓存的。
而post是非幂等的,即除了返回数据还会有其他副作用,所以post是不安全的,必须交由web服务器处理,即 不可缓存
从数据传输方面:
get和post本质上是tcp连接,并无差别。由于http的规定和 浏览器/服务端的限制导致他们在应用过程中出现一些不同。
在响应时,get产生一个tcp数据包,post产生两个tcp数据包
对于get方式的请求,浏览器会把header和实体主体一并发送出去,服务端响应200,返回数据
对于post,浏览器先发送header,服务器响应100 continue,浏览器再发送实体主体,服务器响应200 OK
get 相对于post 的优势
- 方便,get的url 可以直接手动输入
- 可以被缓存,大大减轻服务器负担
无连接,无状态
- http无状态
即协议对事物处理没有记忆能力。
每次的请求都是独立的,它执行情况和结果与前面的请求和之后的请求是没有直接关系的,他不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况。也就是说服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器。
标准的HTTP协议指的是不包括cookies,session,application 的HTTP协议 - HTTP的持久连接
- 非持久连接:每个连接处理一个 请求-响应 事务
- 持久连接:每个连接可以处理多个 请求-响应 事务
持久连接的情况下,服务器发出响应后让tcp连接继续打开着。同一对 客户/服务器 之间的后续请求和响应可以通过这个链接发送
HTTP/1.0 使用非持久连接 HTTP/1.1默认使用持久连接<keep-alive>
非持久连接的每个连接,tcp得在客户端和服务端分配tcp缓冲区,并维持tcp变量,会严重增加服务器的负担。而且每个对象都有2个rtt(也就是一个数据包从发送到回来的时间)延迟,由于tcp的拥塞控制方案,每个对象都会遭受tcp缓启动,因为每个tcp连接都起始于缓启动阶段
HTTP持久连接怎么判断一个请求是否结束
- content-length:根据所接收字节数是否达到content-length值
- chunked(分块传输):
Transfer-Encoding
当选择分块传输时,响应头中可以不包含content-length
,服务器会先回复一个不带数据的报文(状态行 和 首部行),然后开始传输若干个数据块。当传输完若干个数据块后,需要再传输一个空的数据块,当客户端接收到空的数据块时,则客户端知道数据接收完毕。
网友评论