介绍
TCP 数据包简单介绍
-
标识位
- SYN – synchronous 建立连接
- ACK – acknowledgement 确认
- FIN – finish 结束
-
其他
- seq 顺序号码
- ack 确认号码
三次握手
-
流程
-
第一次握手
发送方首先发送一个带有 SYN 标志的数据包给对方, 表示请求建立连接
数据包内容: SYN = 1, seq = m(随机数) -
第二次握手
接收方收到后, 回复一个带有 SYN/ACK 标志的数据包(传递确认信息), 表示我收到了
数据包内容: SYN = 1, ACK = 1, ack = m+1, seq = n(随机数) -
第三条握手
发送方回复一个带有 ACK 标志的数据包, 表示连接建立成功
数据包内容: ACK = 1, ack = n+1
-
-
图解
四次挥手
-
流程
-
第一次挥手
A(申请断开方)发送一个带有 FIN 标志的数据包, 表示我不再发送数据了
数据包内容: FIN=1, seq=x(随机数) -
第二次挥手
B(接收方)收到后, 回复一个带有 ACK 标志的数据包, 我收到了, 但此时接收方可能会继续发送数据
数据包内容: ACK = 1, ack=x+1 -
第三次挥手
B(接收方)发送一个带有 FIN 标志的数据包, 表示我发完了, 并且我也不再发送数据了
数据包内容: FIN=1, seq=y(随机数) -
第四次挥手
A(申请断开方)回复一个带有 ACK 标志的数据包, 表示连接断开
数据包内容: ACK=1, ack = y+1
-
-
图解
QA
为什么要有三次握手和四次挥手
- TCP协议面向连接的, 所有传输数据前必须先建立连接
- 三次握手是为了建立连接的,建立连接时 接收方的ACK和SYN是在一个报文中发送的
- 四次挥手是为了断开连接,断开连接时, 接收方的ACK和FIN是分两次发送的
为什么四次挥手的ACK和FIN要分开发送
- 因为FIN只表示发送方"我"不再发送收据, 但仍可以接收数据
- 这时己方可以选择直接断开连接, 也可以选择继续发送数据给对方,直到发送完成后,再断开连接
问题处理
timewait 过多
-
原因
- timewait 是“断开发起方”的状态
- 该状态处于已经向“被断开方发”送 ack 之后,等待系统销毁期间
- 所以过多的原因一般是因为短期内断连太多导致
-
处理
# from https://blog.csdn.net/MiSiTeLin/article/details/115218672 /etc/sysctl.conf # 对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,不应该大于255,默认值是5,对应于180秒左右时间 net.ipv4.tcp_syn_retries=2 #net.ipv4.tcp_synack_retries=2 # 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为300秒 net.ipv4.tcp_keepalive_time=1200 net.ipv4.tcp_orphan_retries=3 # 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间 net.ipv4.tcp_fin_timeout=30 # 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。 net.ipv4.tcp_max_syn_backlog = 4096 # 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭 net.ipv4.tcp_syncookies = 1 # 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭 net.ipv4.tcp_tw_reuse = 1 # 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭 net.ipv4.tcp_tw_recycle = 1 # 减少超时前的探测次数 net.ipv4.tcp_keepalive_probes=5 # 优化网络设备接收队列 net.core.netdev_max_backlog=3000
closewait 过多
-
原因
- 接收请求断开并回复后,被动断开方就处于 closewait 状态
- 过多表示没有发送自己的 fin
- 检查当时是否有数据未发送完成,如果流量为空,需要检查后端代码是否调用 socket close() 方法
-
处理
- 有流量表示数据未传输完成
- 无流量表示代码未释放 socket 连接