0%

tcp原理和三次握手四次挥手

1. tcp 和 udp

1

UDPTCP
数据传输数据传输3报文握手+数据传输+4报文挥手
连接方式单播(一对一), 多播(一对多), 广播 (一对全)单播(一对一)
应用报文每个报文添加个UDP首部一系列字节流放到缓存中, 通过滑动窗口策略发送
发送方加个 TCP 头部
接收方取出字节流,组合送给接收方进程
首部8字节最小20字节, 最大60字节

1.1 tcp socket 模型

img

1.2 udp socket 模型

img

1.3 tcp 头部字段

1. 头部格式

20字节固定 + 最大40字节扩展

2. 固定20字节详情
  • 源端口 2字节, 目的端口 2字节

  • 序号 4字节 , 我发送的是以 n 开始的序号

  • 确认号 4字节, 之前的都已经接收,下次希望给我传递 n, ACK位置必须=1

  • 数据偏移(说明头部字节是20还是到60) + 保留 + URG(紧急指针有效) + ACK + PSH(推送,尽快交给应用层) + RST(复位,重新建立连接) + SYN(tcp建立标志) + FIN(tcp释放标志) 一共2字节, 窗口2字节, 我的接收窗口大小 (例如rwnd=20)

  • 检验和2字节(检错算法), 紧急指针2字节(帮忙取出紧急数据)

3. 最大40字节扩展字段

1

2. tcp 建立连接

1

2.1 客户端

  • 首先处于 closed 状态

  • 创建传输控制快

  • 1️⃣ 发送握手①SYN=1 seq=x 进入SYN-SENT(同步已发送状态)

  • 3️⃣ 发送握手③ACK=1 seq=x+1 ack=y+1 进入 ESTABLISHED(连接已建立状态)

  • 开始数据传输

2.2 服务端

  • 首先处于 closed 状态

  • 创建传输控制快

    • tcp 连接表

    • 指向发送和接收缓存的指针

    • 指向重传队列的指针

    • 当前的发送和接收序号

  • listen 监听

  • 2️⃣ 发送握手② SYN=1 ACK=1 seq=y ack=x+1 进入SYN-REVD (同步已接收状态)

  • 进入ESTABLISHED(连接已建立状态)

  • 开始数据传输

3. tcp 释放连接

1

3.1 主动端

  • 1️⃣ 发送挥手① FIN=1 ACK=1 seq=u ack=v 进入 FIN_WAIT_1(终止等待1状态)

  • 收到挥手②进入 FIN_WAIT_2(终止等待2状态)

  • 接受数据

  • 4️⃣ 发送挥手④ ACK=1 seq=u+1 ack=w+1 进入 TIME_WAIT(时间等待状态)

  • 经过2MSL后, 进入 CLOSED(关闭状态)

3.2 被动端

  • 2️⃣ 发送挥手② ACK=1 seq=v ack=u+1 并进入CLOSE_WAIT(关闭等待状态)

  • 通知应用进程断开连接, 客户端到服务器方向连接关闭, 属于半关闭状态

  • 发送未发完的数据

  • 3️⃣ 发送挥手③ FIN=1 ACK=1 seq=w ack=u+1 进入 LAST-ACK(最后确认状态)

  • 收到挥手④后进入 CLOSED(关闭状态)

4. tcp 可靠性

4.1 如何保证可靠性

  1. 基于数据块传输:应用数据被分割成 TCP 认为最适合发送的数据块,再传输给网络层,数据块被称为报文段或段。
  2. 对失序数据包重新排序以及去重:TCP 为了保证不发生丢包,就给每个包一个序列号,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据就可以实现数据包去重。
  3. 校验和 : TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
  4. 超时重传 : 当发送方发送数据之后,它启动一个定时器,等待目的端确认收到这个报文段。接收端实体对已成功收到的包发回一个相应的确认信息(ACK)。如果发送端实体在合理的往返时延(RTT)内未收到确认消息,那么对应的数据包就被假设为已丢失并进行重传。
  5. 流量控制 : TCP 连接的每一方都有固定大小的缓冲空间,TCP 的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议(TCP 利用滑动窗口实现流量控制)。
  6. 拥塞控制 : 当网络拥塞时,减少数据的发送。

4.2 为什么不两次握手

假如第一个连接发送失败,重传后过了好久好久,到达了。

服务器对失败后的连接又建立了一次请求, 但客户端可能处于关闭了都无法理会,服务器就无法释放这个连接。

4.3 为什么 TIME_WAIT

参考:https://www.liuvv.com/p/7b71ec65.html

因为客户端发送挥手④的时候,有可能失败。

如果客户端直接关闭,服务器重发挥手③,客户端处于关闭不响应,服务器无法释放资源。

4.4 保活计时器

假如建立连接后, 客户端出现了故障

  • 服务器每次收到请求后, 重新启动定时器(2小时)。
  • 服务器2小时后没收到客户端请求,发送探测报文段。
  • 服务器75秒间隔发送一个,达到10个无响应,关闭连接。

4.5 流量控制和拥塞控制

参考:https://www.liuvv.com/p/7eb83068.html

5. 头脑风暴

  • socket 过程:服务器 bind+listen+for(accept),客户端 connect,相互 read+write。
  • 三次握手:SYN+ 序列号,SYN+ACK+ 序列号增加,ACK+ 序列号增加,最后进入 ESTABLISHED。
  • 四次挥手:客户端 FIN,服务器 ACK 进入 CLOSE_WAIT,服务器继续发消息,服务器 FIN,客户端 ACK 进入 TIME_WAIT。
  • TIME_WAIT: 只是主动端特有的状态。如果不等待直接close,万一第四次挥手失败,服务器重发得不到响应,无法释放。

6. 参考资料

给作者打赏,可以加首页微信,咨询作者相关问题!