小林coding计网-TCP篇
1. 三次握手、四次挥手

TCP | 特点 |
---|---|
为什么需要TCP? | IP层不可靠,不保证网络包的交付和数据完整性 TCP确保无损坏、无间隔、非冗余、按序 |
连接的基本共识 | Socket:IP号 + 端口号 序列号:解决乱序问题 窗口大小:流量控制 |
如何唯一确定? | 四元组 地址字段在IP头,端口字段在TCP头 |
TCP最大连接数? | 理论上max = 客户端IP数 * 客户端端口数 ,实际受FD和内存的限制 |
TCP | UDP | |
---|---|---|
连接和方式 | 面向连接、可靠、字节流 | 无连接、不可靠、数据报 |
连接对象 | 一对一(单播) | 一对一、一对多、多对一、 多对多(单播、多播、广播) |
拥塞控制 | 有拥塞控制 | 无 |
首部开销 | 至少20字节 | 8字节 |
分片机制 | 如果HTTP消息比MSS 长,就要在传输层 分片 | UDP数据如果大于MTU ,在IP 层分片 |
使用场景 | 实时应用,包括: 音视频、多媒体 包总量少的通信,如 DNS 、SNMP 等 | FTP 文件传输、HTTP/S |

为什么是三次握手:
- 避免历史连接:如果因为宕机重发,最好在「被动发起方」建立连接前阻止历史连接,就不会资源浪费,而这样就需要三次握手
- 同步双方初始序列号:
序列号
作用:不重复、不丢弃、按序传输 - 避免资源浪费:服务端每收到一个SYN只能建立一个连接(因为不知道客户端是否收到自己的ACK),可能有冗余连接
初始化序列号不一样?
为了防止历史报文被下一个相同四元组的连接接收。有时前一条数据因故阻塞,恰好服务端断电重启了,再重新建立连接,之前阻塞的消息再到达后会出bug。总而言之,为了防止上一次连接的数据被下一次连接接收
TCP为什么需要MSS?
先看定义:
MTU
:一个网络包的最大长度,以太网中一般为 1500 字节MSS
:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度
IP没有超时重传机制,如果有一个IP分片丢失,那么整个IP报文分片都得重传;所以为了传输效能,TCP建立连接时协商MSS
值,由此分片后IP包也不回大于MTU
,此后如果一个TCP分片丢失了,重发时也只是以MSS为单位
第一次握手丢失了,发生什么?
客户端重传第一次握手SYN
报文。第一次超时重传是在1秒后,每次重传时间是上一次的2倍,第5
次重传(重传次数由内核参数决定)后,会等待32秒,如果还没回应就断开连接
第二次握手丢失了,发生什么?
两边都会重传:客户端重传第一次握手SYN
报文,最大重传次数由tcp_syn_retries
内核参数决定。服务端重传第二次握手SYN-ACK
报文,最大重传次数由tcp_synack_retries
内核参数决定
第三次握手丢失了,发生什么?
服务端重传第二次握手SYN-ACK
报文
SYN攻击:攻击者伪造不同IP发送SYN
报文,服务端发出去的ACK+SYN
无应答,占满半连接队列
SYN攻击避免方式:
- 修改Linux内核参数,控制队列大小和队满处理方式
tcp_syncokies
方法。半连接队列满了后,新收到的SYN
包计算出cookie值,返回给客户端;再收到客户端的应答报文时,检查合法性后直接放入全连接队列

为什么需要四次?
假设客户端主动关闭连接,客户端发送FIN
时,仅仅表示客户端不发数据了,但还能接收数据。服务端可能还有数据处理发送,待不再发送时,才回FIN
给客户端
第一次挥手丢失了,发生什么? 重传第一次挥手FIN
报文,最大次数由tcp_orphan_retries
决定;超过最大次数后再等待两倍时间就会断开
第二次挥手丢失了,发生什么? 重传第一次挥手FIN
报文(ACK
报文是不会重传的)。对于调用close
关闭的连接,60秒内没有收到FIN
报文,主动关闭方就会关闭连接
第三次挥手丢失了,发生什么? 和第一次挥手丢失后有些类似,重传并等待第四次挥手,超过参数后断开连接
第四次挥手丢失了,发生什么? 重传第三次挥手FIN
报文。客户端接收到 FIN
后发送 ACK
,进入TIME_WAIT
状态并等待2MSL
的时间。如果在 2MSL
时间内,因为客户端的 ACK
没有传输到服务端,客户端又接收到了服务端重发的 FIN
报文,那么 2MSL
时间将重新计时
为什么需要TIME_WAIT?
2MSL
的时间足以让原来连接的数据包都自然消失,防止历史连接数据被相同四元组错误连接接收- 保证正确关闭。如果没有
2MSL
,客户端直接CLOSE
,如果服务端再向已关闭的客户端发送FIN
报文,客户端会回RST
报文,不属于正常关闭了
客户端TIME_WAIT 过多 | 服务端TIME_WAIT 过多 | |
---|---|---|
危害 | 占用端口资源,很难和目的IP + Port 一样的服务器建立连接,但只要是不同的服务器还是可以重复使用的 | 因为服务器只监听一个端口,不会导致端口资源受限;但是会占用系统资源,比如fd、内存、CPU等 |
TCP | 客户端出现故障 | 服务端出现故障 |
---|---|---|
建立连接后 | socket设置SO_KEEPALIVE 启动保活机制,定时检测客户端故障造成的死亡连接 | 服务端会发送FIN 和客户端进行挥手 |