HTTP协议简介
HTTP协议是超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个请求/响应协议。客户端发送请求给服务端,服务端回复给客户端一个响应。是基于TCP/IP的关于数据如何在万维网上进行通信的协议
HTTP协议特点
- HTTP协议是一种无状态协议,服务器不保存与客户端连接时的任何状态,指的是客户端与服务器之间不需要建立持久的连接,当客户端向服务器发送请求,服务器返回响应之后,该连接就被关闭了,服务器上不保存连接的信息。大大减轻了服务器的负担,保证了较快的响应速度,但是无状态也意味着,如果下一步操作需要之前的信息,那么就必须重传,可能会导致每次连接的数据量较大
- 对数据格式不做要求,HTTP协议允许传输任意类型的数据,传输的数据类型在头部,用Content-Type表示
- 通信简单,在向服务器发送请求时,只需发送请求方法和路径
- 无连接,每次连接只处理一个请求,当这个请求处理完毕后,就断开连接
HTTP协议格式
HTTP协议格式:首行+url+头部字段+正文
- HTTP请求报文格式:
1.请求行:包含请求方法,URL,HTTP协议版本
2.请求头部字段
3.空行(必须有)
4.请求内容实体
GET http://192.168.21.1/admin HTTP/1.1
Accept: */*
Accept-Languaage: en-us
Connection: Keep-Alive
Host: localhost
//空行
请求的内容实体
- HTTP响应报文格式:
1.状态行:包含HTTP协议版本,影响状态码,状态码描述
2.响应头段字段
3.空行(必须有)
4.响应内容实体
HTTP/1.1 200 ok
Date: ...
Content-Length: 1000
Content-Type: text/html
Cache-control: private
//空行
<HTMl>
<BODY>
请求方法
GET/POST/HEAD/PUT/DELETE/CONNECT/PATCH/OPTIONS/TRACE
方法 | 说明 | 支持的HTTP协议版本 |
---|---|---|
GET | 对服务器资源的简单请求 | 1.0,1,1 |
POST | 传输实体主体 | 1.0,1.1 |
PUT | 传输文件 | 1.0,1.1 |
HEAD | 获得报文首部 | 1.0,1.1 |
DELETE | 删除文件 | 1.0,1.1 |
OPTIONS | 询问支持的方法 | 1.1 |
TRACE | 追踪处理进程 | 1.1 |
CONNECT | 要求用隧道协议连接代理 | 1.1 |
LINK | 建立和资源之间的联系 | 1.0 |
UNLINE | 断开连接关系 | 1.0 |
GET与POST的区别
GET:从指定的资源请求资源
POST:向指定的资源提交要被处理的数据
数据存放位置 | 数据安全 | 明文密文 | 长度限制 | 参数类型 | 编码方式 | 参数保留 | 幂等 | |
---|---|---|---|---|---|---|---|---|
GET | path中 | 不安全 | 明文 | 受url限制,一般为2k | 只接受ASCII字符 | 只能url编码 | 保留在浏览器历史记录中 | 幂等 |
POST | 正文中 | 安全 | 密文 | 没有限制 | 没有限制 | 支持多种编码方式 | 不会保留 | 非幂等 |
注意:
- 为什么GET有长度限制?
这里的限制其实指的是url的长度限制,由于HTTP协议本身对url长度没有做限制,实际的限制是由客户端/浏览器以及服务器决定的。通常所说的2k限制,指的是IE8的限制。对于服务器来说,过长的url处理起来是一种负担,所以出于安全,稳定等因素,服务器会给url的长度加上限制,所以GET看起来长度就有了限制 - 为什么说GET不如POST安全?
因为GET使用url传输,而POST使用body传输数据,所以GET不如POST安全。但是从攻击的角度来说的话,因为HTTP协议就是一个明文协议,每个HTTP请求和响应都会明文传播,无论url,header,body都会明文显示,所以为了避免传输中数据发生泄露,必须使得客户端到服务器都进行加密,通常采用https保证安全性 - POST为什么不是幂等的?
幂等:操作没有副作用。
非幂等就意味着不能随意多次执行,也不能缓存
如果通过POST下一个单,然后服务器创建了一个新的订单,在返回订单成功的页面(这是正常的情况下),但是如果POST请求被浏览器缓存,那么这个下单请求就可以不向服务器发送,直接返回本地缓存的成功页面,但是不向服务器发送的话,后续操作会无法进行 - GET为什么是url编码?
- GET请求放在url中是明文的,如果不进行编码则隐私性较低
- 防止出现字符串歧义
url
http://用户名:密码@域名(服务器)IP:端口/资源路径?查询字符串#片段标识符
域名:服务器的别名,通常是容易记忆的字符串,但是最终仍旧需要解析为服务器IP地址才能访问服
务器
端口:HTTP:80 / HTTPS:443
资源路径:服务器上的相对根目录,表示了资源在服务器上的路径
查询字符串:以key=val形式的键值对组成,键值对之间以&符号间隔—key=val&key=val
urlencode: url的资源路径以及查询字符串中若存在特殊字符,此时就需要进行转义,将特殊字符每个字节转换为16进制数字字符,并且前缀%用于表示转义
urdecode:在url中遇到%,将其后面的两个字符转换为数字,第一个数字乘以16,再加上第二个数字
urldecode就是urlencode的逆过程
HTTP协议版本
- 0.9: 不完善的版本,没有当前的协议格式,并且只支持文字的超文本数据传输、只有GET请求方法
- 1.0: 规范了协议格式,支持了不同文件格式的数据流,增加了请求方法
- 1.1: 考虑了传输性能问题,增加了请求方法,头部描述信息,实现了管线化传输,长连接传输
- 2.0: 改进了之前版本协议的冗余问题,使用二进制流传输,进行多路复用,允许服务器主动推送数据
长连接与短连接
长短连接本质上是TCP连接,HTTP协议基于请求/响应,给出响应之后本次连接就断开了。
短连接:http基于tcp实现通信,短连接指的是建立连接,发送一个请求,得到响应之后则断
开连接
- 连接->数据传输->关闭连接
长连接:将Connection设置为keep-alive(客户端与服务端都需要设置)就打开长连接。
- 长连接情况下,多个HTTP请求可以复用同一个TCP连接,节省了很多TCP连接建立和断开
的消耗 - 注意长连接不是永久性连接的,在一段时间内(这个时间长短可以在header中设置),这个
连接没有发出HTTP请求的话,就会断开连接
长短连接应用场景
- 1.长连接多用于连接频繁,点对点的通讯,并且连接数不能太多的情况
- 2.如web网站则使用短连接,因为长连接更加浪费资源,因为web网站有大量的客户端
(1.1版本) 管线化传输:一次连接中,连续发送多个请求,按照顺序响应(之前的版本是发送一个请求响应一个)
(2.0版本)多路复用:响应顺序可以不用按照请求顺序响应,在头部中标识了属于的请求信息
响应状态码
响应状态码:表示本次请求服务端做出的响应结果
- 1xx:请求已被接收,请求处理中,
- 2xx:表示本次请求服务端正确响应
200 ok – 客户端请求成功 - 3xx:重定向 - 请求的资源已经迁移到另一个位置(原有链接依旧可用) 要求客户端重新请求新的
301 – 永久重定向,域名跳转
302 – 临时重定向 - 4xx:表示客户端请求错误
400 – 请求错误
403 – 服务器收到请求,拒绝提供服务
404 – 表示请求的资源不存在 - 5xx:表示服务端错误
500 – 服务器内部错误
502 – 代理请求失败/无效响应
503 – 服务器不能处理客户端的请求,一段时间后可能恢复正常
504 – 代理请求超时
典型的头部信息
Content-Type | 正文类型 |
Content-Length | 正文长度(解决http数据粘包问题) |
Location | 重定向新的资源位置 |
Cookie | 连续传输,用于持久保持客户端的通信状态,cookie使用不安全,所以通常搭配Session使用 |
Set-Cookie | 服务端通过这个描述符向客户端传递信息,并且保存在客户端浏览器的cookie文件中 |
Session | 不是头部字段,是服务端为每个建立的会话信息,因为Cookie传输信息不安全,因此服务器创建会话,保存客户端状态信息,将session通过Cookie返回 |
Cookie与Session的区别
- Session在服务器端,Cookie在浏览器(客户端)
- Session可以放在文件,数据库,内存中
- Session的运行依赖sessionid,而sessionid是存在Cookie中的,所以当浏览器禁用了Cookie那么,session也会失效(此时可以通过在url参数中传递sessionid)
空行
\r\n 间隔头部或者正文;接收http数据的时候,当连续接收两个 \r\n 的时候,则认为头部到此结束
先获取完整头部,通过头部中的Content-Length获取正文长度,然后获取指定长度正文,通过这种方式每次获取完整的一条http请求数据