TCP
传输控制协议(Transmission Control Protocol)
- 数据单位协议:UDP报文、用户数据报
特点
- 面向连接的运输层协议
- 每一条 TCP 连接只能有两个端点 (endpoint),每一条 TCP 连接
只能是点对点
的(一对一) - 提供可靠交付的服务
- 提供全双工通信
- 面向字节流
- 但 TCP 传送的数据单元却是报文段
- TCP 不提供广播或多播服务
- 首部的前 20 个字节是固定的,后面有 4n 字节是根据需要而增加的选项 (n 是整数)
- 因此 TCP 首部的最小长度是 20 字节
建立连接三次握手
三报文握手主要是为了防止已失效的连接请求报文段突然又传送到了,因而产生错误。
起初,两端都为 CLOSED 状态。在通信开始前,双方都会创建 TCB。 服务器创建完 TCB 后便进入 LISTEN 状态,此时开始等待客户端发送数据
- 第一次握手
- 客户端发送的SYN=1(同步序列号seq=x)的包到服务端并变为SYN-SENT(请求连接)状态,等待服务端响应
- 第二次握手
- 服务端收到客户端请求后,发送一个包(SYN=1,ACK=1,seq=y,ack=x+1)给客户发端,服务端进入SYN_RECEVIED状态
- 第三次握手
- 客户端收到服务端响应的包(SYN=1,ACK=1)后,再向服务端发送确认包(ACK=1,seq=x+1,ack=y+1),发送完毕,客户端和服务端都进入ESTABLISHED状态,完成握手
连接释放四次挥手
数据传输结束后,通信的双方都可释放连接
TCP 是全双工的,在断开连接时两端都需要发送 FIN 和 ACK
- 第一次挥手
- 客户端认为数据发送完成,向服务端发送链接释放请求(FIN=1,序号seq=u),等待服务端确认
- 第二次挥手
- 服务端收到请求后,通知应用层要释放 TCP 链接。然后会发出确认包(ACK =1,seq=V,ACK=u+1),并进入 CLOSE_WAIT 状态
- 此时表明 客户端 到 服务端 的连接已经释放,不再接收 客户端 发的数据了
- 但是因为 TCP 连接是双向的,此时处于半关闭状态服务端 仍旧可以发送数据给 客户端
- 服务端如果此时还有没发完的数据会继续发送
- 第三次挥手
- 服务端发送完毕后向 客户端 发送连接释放请求(FIN=1,ACK=1,seq=w,ack=u+1),然后 服务端 便进入 LAST-ACK 状态
- 第四次挥手
- 客户端收到连接释放报文段后,向服务端发送确认应答
- 然后 客户端 进入 TIME-WAIT 状态
- 该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 服务端 收到确认应答后,也便进入 CLOSED 状态。
首部格式
- 源端口:2字节
- 目的端口:2字节
- 端口是运输层与应用层的服务接口。运输层的复用和分用功能都要通过端口才能实现
- 序号:4 字节
- TCP 连接中传送的数据流中的每一个字节都编上一个序号
- 序号字段的值则指的是本报文段所发送的数据的第一个字节的序号
- 报文段的序号字段值=301,而携带的数据共有100字节,则本报文段的数据第一个字节序号是301,最后一个字节的序号是400.那么下一个报文段的数据序号应当是401
- 确认号:4 字节,是期望收到对方的下一个报文段的数据的第一个字节的序号
- 若确认号=N 则表示:到序号N-1为止的所有数据都已正确收到
- 如果接收方B收到A发送过来的报文段,序号=501,数据长度是200字节,表明B收到了A发送的到序号700为止的数据。则B发送给A的确认报文段中把确认号设置为701
- 数据偏移:4位,指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远
- 单位是4字节
- 实际上是TCP报文段的首部长度
- 最大TCP报文段首部=60字节=(2^4-1)*4
- 保留字段:6 位,保留为今后使用
- 目前应置为 0
- URG:1位,紧急(urgent)
- 当 URG为1 时,表明紧急指针字段有效,它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)
- ACK:1位,确认(acknowledge)
- ACK=1时确认号才有效
- PSH:1位,推送(push)
- PSH = 1 的报文段,就尽快地交付接收应用进程,而不再等到整个缓存都填满了后再向上交付
- RST:1位,复位(reset)
- RST=1,TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接
- SYN:1位,同步(synchronous)
- SYN = 1 表示这是一个连接请求或连接接受报文
- SYN=1 ACK=0: 连接请求报文段
- SYN=1 ACK=1:连接接收报文段
- FIN:1位,终止(finish)
- FIN = 1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接
- 窗口字段:2 字节-窗口是发送本报文段的一方的接收窗口,是用来让对方设置发送窗口的依据
- 如确认号=701,窗口字段=1000,则表示告诉对方:从701号开始,我的接收缓存还可以接收1000字节
- 检验和:2 字节,检验和字段检验的范围包括首部和数据这两部分
- 在计算检验和时,要在 TCP 报文段的前面加上 12 字节的伪首部
- 紧急指针字段:2字节,指出在本报文段中紧急数据共有多少个字节(紧急数据放在本报文段数据的最前面)
- 选项字段:长度可变
- TCP 最初只规定了一种选项,即最大报文段长度 MSS
- MSS 告诉对方TCP:“我的缓存所能接收的报文段的数据字段的最大长度是 MSS 个字节。”
- 数据字段加上 TCP 首部才等于整个的 TCP 报文段
- 所以,MSS是“TCP 报文段长度减去 TCP 首部长度”
- 填充字段:这是为了使整个首部长度是 4 字节的整数倍
可靠传输工作原理
停止等待ARQ
每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。
连续ARQ
发送方维持的发送窗口,它的意义是:位于发送窗口内的分组都可连续发送出去,而不需要等待对方的确认。这样,信道利用率就提高了
连续 ARQ 协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。
流量控制
流量控制所要做的就是抑制发送端发送数据的速率,以便使接收端来得及接收
利用滑动窗口实现流量控制
拥塞控制
拥塞控制就是防止过多的数据注入到网络中,使网络中的路由器或链路不致过载
- TCP 采用基于窗口的方法进行拥塞控制。该方法属于闭环控制方法。
- TCP发送方维持一个拥塞窗口 CWND
- 拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。
- 发送端利用拥塞窗口根据网络的拥塞情况调整发送的数据量。
- 所以,发送窗口大小不仅取决于接收方公告的接收窗口,还取决于网络的拥塞状况,所以真正的发送窗口值为:min(公告窗口值,拥塞窗口值)
拥塞的判断
- 重传定时器超时
- 收到三个相同重复的ACK
四种控制算法
- 慢开始:由小到大逐渐增大拥塞窗口数值
- 拥塞避免:让拥塞窗口 cwnd 缓慢地增大,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,而不是加倍,使拥塞窗口 cwnd 按线性规律缓慢增长
- 快重传:让发送方尽早知道发生了个别报文段的丢失
- 发送方只要一连收到三个重复确认,就知道接收方确实没有收到报文段,因而应当立即进行重传
- 快恢复:当发送端收到连续三个重复的确认时,由于发送方现在认为网络很可能没有发生拥塞,因此现在不执行慢开始算法,而是执行快恢复算法
适合场景
- HTTP
- FTP
- SMTP
- 文件传输
- 游戏。。。
TCP与UDP相关问题
1.为什么 TCP 建立连接需要三次握手,明明两次就可以建立起连接?
- 防止出现失效的连接请求报文段被服务端接收的情况,从而产生错误
- 如果只有1次:客户端收到请求后,没收到应答,无法判断链接是否连接成功
- 如果只有2次:
- 客户端发送连接请求后,等待服务器端的应答。
- 如过客户端的SYN过了一段时间没有到达服务器端,客户端链接超时,会重新发送一次连接请求
- 如果重发的这次服务器端收到了,且应答了客户端,连接就建立了
- 但是建立后,第一个SYN也到达服务端了,这时服务端会认为这是一个新连接,会再给客户端发送一个ACK,这个ACK当然会被客户端丢弃
- 但是此时服务器端已经为这个连接分配资源了,而且服务器端会一直维持着这个资源,会造成浪费
2.三次握手过程中可以携带数据么?
- 第三次可以携带
- 客户端已经处于ESTABLIEISH状态,已经能够确认服务端的接收,发送能力正常,这个时候可以携带
- 前两次不可以
- 一旦有人想攻击服务器,只需要在第一次握手中的 SYN 报文中放大量数据,那么服务器会消耗更多的时间和内存空间去处理这些数据,增大了服务器被攻击的风险
3.为什么 A 要进入 TIME-WAIT 状态,等待 2MSL 时间后才进入 CLOSED 状态
MSL -- Maximum Segment Lifetime -- 报文最大生存时间,最长报文寿命
- 为了保证 客户端 发送的最后一个 ACK 报文段能够到达 服务端
- 防止 “已失效的连接请求报文段”出现在本连接中
- 若 客户端 发完确认应答后直接进入 CLOSED 状态,如果确认应答因为网络问题一直没有到达,那么会造成 服务端 不能正常关闭。
- 如果不等待客户端直接关闭,当服务端还有数据包要发送给客户端时,且还在传输的路上,若客户端的端口此时刚好被新的应用占用,那么就接收到了无用数据包,造成数据包混乱
- 2MSL意义:
- 1 个 MSL 确保四次挥手中主动关闭方最后的 ACK 报文最终能达到对端
- 1 个 MSL 确保对端没有收到 ACK 重传的 FIN 报文可以到达
- 经过2MSL,可以使本链接持续时间内所产生的所有报文段,都从网络中消失
4.TCP与UDP的区别
- UDP 协议是面向无连接的:不需要在正式传递数据之前先连接起双方
- UDP 协议只是数据报文的搬运工:不保证有序且不丢失的传递到对端
- UDP 协议也没有任何控制流量的算法
- UDP 相较于 TCP 更加的轻便
- UDP 的首部开销小,只有 8 个字节,比 TCP 的 20 个字节的首部要少得多
- TCP面向连接的
- 基本与UDP反着来
- 建立连接3次握手
- 断开连接4次挥手
- 通过各种算法保持保证传输的可靠性
HTTP
超文本传输协议(HyperText Transfer Protocol)),基于TCP实现的应用层协议
特点
- 请求响应模型:客户端发送请求,服务端响应请求
- 无状态协议:不需要建立持久链接
工作过程
- 地址解析
- 封装HTTP请求数据包
- 封装成TCP包,建立TCP链接
- 客户端发送请求
- 服务端响应
- 关闭TCP链接
- 保持链接的方案:在请求/响应头中加入
Connection:keep-alive
就可以保持链接打开状态
请求构成
- 请求行
- 首部
- 实体
响应构成
- 协议/版本号 状态码
- 首部
- 实体
请求行
GET /images/logo.gif HTTP/1.1
由请求方法、URL、协议版本组成
请求方法
请求方法分为很多种,最常用的也就是 Get 和 Post 了。虽然请求方法有很多,但是更多的是传达一个语义,而不是说 Post 能做的事情 Get 就不能做了
- Get:应该只被用于获取数据
- Post:用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用.
- Put:求有效载荷替换目标资源的所有当前表示,即更新操作.
- Delete:删除指定的资源
- Patch:用于对资源应用部分修改
- Head:请求一个与GET请求的响应相同的响应,但没有响应体.
- Connect:建立一个到由目标资源标识的服务器的隧道
- Options:描述目标资源的通信选项
- Trace:沿着到目标资源的路径执行一个消息环回测试。
URI
Uniform Resource Identifier
--统一资源标识符,用于区分互联网上不同资源
URI
包含 URL
与 URN
URI只能使用ASCII, ASCII 之外的字符不支持显示,因此,URI 引入了编码机制,将所有非 ASCII 码字符和界定符转为十六进制字节值,然后在前面加个%
URL
scheme://host:port/path?query
- scheme:协议,HTTP,HTTPS,FTP
- host:主机名,sugarat.top
- port:端口号,默认80,https默认443
- path:资源路径
- query:用于查询的参数
URN
path?query
副作用和幂等
- 副作用:指对服务器上的资源做改变
- 搜索是无副作用的,注册是副作用
- 幂等:指发送 M 和 N 次请求(两者不相同且都大于 1)
- 服务器上资源的状态一致,比如注册 10 个和 11 个帐号是不幂等的
- 对文章进行更改 10 次和 11 次是幂等的。因为前者是多了一个账号(资源),后者只是更新同一个资源。
常见首部
通用首部
字段 | 作用 |
Cache-Control | 控制缓存的行为 |
Connection | 浏览器想要优先使用的连接类型,比如 keep-alive |
Date | 创建报文时间 |
Pragma | 报文指令 |
Via | 代理服务器相关信息 |
Transfer-Encoding | 传输编码方式 |
Upgrade | 要求客户端升级协议 |
Warning | 在内容中可能存在错误 |
请求首部
字段 | 作用 |
Host | 访问资源所在的主机名 |
Accept | 能正确接收的媒体类型(application/json) |
Accept-Charset | 能正确接收的字符集 |
Accept-Encoding | 能正确接收的编码格式列表(gzip) |
User-Agent | 发送请求的客户端信息 |
Referer | 浏览器所访问的前一个页面 |
Accept-Language | 能正确接收的语言列表(zh-CN, zh, en) |
If-Match | 值与请求资源ETag相同才会处理请求 |
If-None-Match | 值与请求资源ETag不相同才会处理请求 |
响应首部
字段 | 作用 |
Age | 资源在代理缓存中存在的时间 |
Server | 服务器名字 |
Content-Length | 告知客户端资源长度 |
Expires | 告知客户端资源失效日期 |
Last-Modified | 告知客户端资源最后一次修改的时间 |
E-tag | 文件指纹,资源唯一标识符 |
Location | 客户端重定向到某个 URL |
Proxy-Authenticate | 向代理服务器发送验证信息 |
cookie
字段 | 作用 |
Cookie | 请求时携带的cookie |
Set-Cookie | 响应时服务端传回的cookie |
压缩相关
字段 | 作用 |
Content-Encoding | 发送端使用的编码方式 |
Accept-Encoding | 接收端支持的编码格式 |
状态码
1xx协议处理的中间状态
101
在HTTP升级为WebSocket的时候,如果服务器同意变更,就会发送状态码 101
2xx成功
200
客户端的请求被服务端正确处理204
请求成功但响应报文不包含实体的主体部分- 206 范围请求,客户端进行了部分请求,服务端返回指定部分的内容
- 205 与204作用一致但要求请求方重置内容
3xx重定向
301
永久性重定向,表示资源已被分配了新的url302
临时性重定向,表示资源临时被分配了新的url304
当客户端拥有可能过期的缓存时,会携带缓存的标识 etag、时间等信息询问服务器缓存是否仍可复用,而304是告诉客户端可以复用缓存- 303 资源存在另一个url,服务端要求客户端使用get请求
- 307 临时重定向,向新的url发送同样的请求
4XX客户端错误
400
请求报文存在语法错误401
发送的请求需要有通过 HTTP 认证的认证信息403
对请求资源的访问被服务器拒绝,资源允许访问,但请求不满足条件404
在服务器上没有找到请求的资源405
当前的请求方法不被允许415
不支持的媒体类型,检查Content-Type
5XX 服务器错误
500
服务器端在收到请求后后,执行相关动作时发生了错误502
bad gate无效网关- 501 表示服务器不支持当前请求所需要的某个功能
- 503 表明服务器暂时处于超负载或正在停机维护,无法处理请求
缺点
- 通信使用明文,可能被窃听
- 不验证通信方的身份,可能遭遇伪装
- 无法证明报文的完整性,有可能遭遇篡改