Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
  • HTTP

  • TCP

    • 网络模型模型
    • TCP三次握手&四次挥手
      • 三次握手
        • 为什么不是两次、四次?
        • 为什么初始化的序列号要求不一样?
        • 第二次握手丢失了发生什么?
        • SYN攻击
      • 四次挥手
        • 出现大量TIME_WAIT状态原因?
        • 保活机制
    • 重传机制
    • 流量控制
    • 拥塞控制
    • TCP与UDP区别
    • TCP和UDP可以使用同一个端口吗?
    • 如何解决粘包?
    • 一个服务端进程最多支持多少条TCP连接?
  • UDP

  • IP

  • 网络安全

  • 计算机网络
  • TCP
Nreal
2023-11-20
目录

TCP三次握手&四次挥手

参考:一篇文章带你熟悉 TCP/IP 协议 (opens new window)

https://juejin.cn/post/6844903510509633550?searchId=20231120234435449A3DCDE9A7242E5EA3#heading-13

# 三次握手

指建立一个 TCP 连接时需要客户端和服务器端总共发送三个包以确认连接的建立;

socket编程中,这个过程由客户端执行connect来触发;

流程图:

三次握手

  1. 第一次握手:客户端标志位SYN置1,随机初始化一个序列号client_isn=j,将数据包发送给服务端,客户端进入SYN_SENT状态,等待服务端确认;

    第一个报文 —— SYN 报文

  2. 第二次握手:服务端接收数据包后由标志位SYN=1得知客户端请求建立连接,服务端标志位SYN和ACK置1,确认应答号置为j+1,也随机初始化一个序列号server_isn=k,并将该数据包发送给客户端以确认连接请求,服务端进入SYN_RCVD状态;

    第二个报文 —— SYN + ACK 报文

  3. 第三次握手:客户端确认后,检查确认应答号是否为j+1,ACK是否为1,是则将确认应答号置为k+1,并将数据包发送给服务端,服务端检查正确后,都进入ESTABLISHED状态;

    第三个报文 —— ACK 报文

# 为什么不是两次、四次?

为什么不是两次?

阻止重复历史连接的初始化;

三次握手避免历史连接

客户端连续多次发送SYN建立连接报文,在网络拥堵情况下:旧的SYN报文比新的SYN报文先到,客户端验证的服务端的确认应答号不正确就回RST报文终止连接,后续新到的SYN报文就可以正常完成三次握手;

如果两次握手,第一次握手就建立连接,导致服务端建立了一个历史连接,浪费服务端资源;

两次握手无法阻止历史连接

# 为什么初始化的序列号要求不一样?

防止历史报文被下一个相同四元组的连接接受;(上一个连接的数据包的序列号正好在服务端的接受窗口内)

# 第二次握手丢失了发生什么?

第二次握手:SYN+ACK报文;

包含了ACK报文, 如果丢失,客户端会认为第一次握手的SYN报文丢失了,客户端就会触发超时重传;

且因为丢失了SYN报文,服务端收不到客户端发送的ACK报文,也会触发超时重传机制,重传SYN-ACK报文;

# SYN攻击

攻击者短时间内伪造不同的IP地址的SYN报文, 服务端每收到一个SYN报文,就会进入SYN_RCVD状态,但服务端不知道客户端的IP,就会将服务端准备发送的ACK+SYN报文打满服务端的半连接队列;

解决:

增大半连接队列;

减少SYN+ACK重传次数;

# 四次挥手

指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开;

在socket编程中,这一过程由客户端或服务端任一方执行close来触发;

流程图:

四次挥手

  1. 第一次挥手:客户端发送一个FIN报文,关闭客户端到服务端的数据传送,客户端进入FIN_WAIT_1状态;

    服务端还可以继续发送数据;

  2. 第二次挥手:服务端收到FIN报文后,先发送ACK应答报文,进入CLOSE_WAIT状态;

    客户端进入FIN_WAIT_2状态,继续等待服务端FIN报文;

  3. 第三次挥手:服务端确定数据发送完成,向客户端发送FIN报文,服务端进入LAST_ACK状态;

  4. 第四次挥手:客户端收到FIN报文后,回一个ACK应答报文,进入TIME_WAIT状态;

    服务端收到ACK报文后,进入CLOSE状态;

    客户端经过2MSL后,自动进入CLOSE状态;

    为什么需要经过2MSL?

    客户端发送最后一个ACK报文,如果发送失败,服务端未收到可以重传,如果客户端等待了2MSL后未收到服务端未收到的回复,则证明服务端已正常关闭;

    MSL:报文最大生存时间;

    为什么设置2MSL?

    发送方的数据包被接收方处理后又向对方发送ACK,一来一回需要等待2倍的时间;

# 出现大量TIME_WAIT状态原因?

说明服务端主动断开了很多TCP连接;

什么场景服务端会主动断开连接?

  • 没有使用长连接;

  • 长连接超时;

    一直使用长连接不会占用资源?

    web服务软件一般都会提供一个参数,指定HTTP长连接超时时间,比如nginx提供的keepalive_timeout参数;

  • 长连接请求数达到上限;

# 保活机制

连接建立后,如果客户端宕机,服务端的TCP连接处于ESTABLISH状态,占用资源;

解决:

保活机制,每隔一个时间间隔,发送一个探测报文,如果连续几个探测报文没有得到响应,则认为当前TCP连接死亡;

网络模型模型
重传机制

← 网络模型模型 重传机制→

Theme by Vdoing | Copyright © 2021-2024
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式