【计算机基础】网络系列(二)TCP
本专栏文章持续更新,新增内容使用蓝色表示。
TCP基础知识
TCP头部结构
TCP头部包含了许多关键字段,这些字段共同协作,实现了TCP的可靠传输:
序列号:一个随机初始化的数字,每发送一次数据,就累加该数据字节数的大小。这个机制解决了网络包乱序问题,确保接收方能够按正确顺序重组数据。
确认应答号:指示下一次期望收到的数据序列号,发送端收到这个确认应答后可以认为该序号之前的数据都已被正常接收。这是解决丢包问题的关键。
控制位:
ACK:为1时表示确认应答字段有效
RST:为1时表示TCP连接出现异常必须强制断开连接
SYN:为1时表示希望建立连接,并在序列号字段进行序列号初始值设定
FIN:为1时表示今后不会再有数据发送,希望断开连接
TCP三次握手
TCP通过三次握手过程建立连接,确保通信双方都能正常收发数据:
第一次握手:客户端随机初始化序列号(x),将SYN标志位设为1,发送SYN报文给服务器,进入SYN-SENT状态。
第二次握手:服务端收到SYN报文后,也随机初始化自己的序列号(y),将确认应答号设为客户端序列号+1(x+1),SYN和ACK标志位都设为1,发送SYN+ACK报文,进入SYN-RCVD状态。
第三次握手:客户端收到SYN+ACK报文后,发送ACK报文,确认号为服务端序列号+1(y+1),进入ESTABLISHED状态。服务端收到ACK后也进入ESTABLISHED状态。
握手机制补充
握手阶段可以携带数据吗?
只有第三次握手可以携带数据,前两次握手主要用于协商参数和同步序列号。
为什么需要三次握手?两次不行吗?
三次握手有两大主要目的:
防止历史重复连接初始化:假设客户端先发送序列号为100的SYN报文,但网络阻塞导致服务端未及时收到。客户端重启后发送序列号为110的新SYN报文。如果旧的SYN报文先到达,服务端会回复SYN+ACK,客户端发现确认号不对,会发送RST报文中止连接。如果是两次握手,服务端在发送SYN+ACK后就建立连接,无法阻止这种历史连接。
同步双方序列号:序列号让接收方能够去除重复数据并按序接收,这是可靠传输的基础。
SYN+ACK报文丢失怎么办?
双方都有超时重传机制。客户端未收到SYN+ACK会重传SYN,服务端未收到第三次ACK会重传SYN+ACK。
服务端内部处理与SYN攻击防护
连接队列机制
服务端收到SYN请求后,内核将连接存储到半连接队列(SYN队列),回复SYN+ACK。收到第三次握手的ACK后,内核将连接移入全连接队列(accept队列),等待应用程序通过accept函数取出使用。
SYN攻击与防护
大量SYN包发送会导致什么?
可能导致TCP半连接队列满,后续SYN报文被丢弃,无法建立新连接。
防护措施:
增大半连接队列长度
开启tcp_syncookies:队列满时,通过算法计算cookie值放入第二次握手的序列号字段,绕过半连接队列
减少SYN+ACK重传次数:Linux默认5次,可适当减少
TCP四次挥手
第一次挥手:客户端发送FIN报文,进入FIN_WAIT_1状态
第二次挥手:服务端回复ACK,进入CLOSE_WAIT状态
第三次挥手:服务端发送FIN报文,进入LAST_ACK状态
第四次挥手:客户端发送ACK,进入TIME_WAIT状态,等待2MSL后关闭
TIME_WAIT状态的重要性
为什么需要TIME_WAIT?
主要目的是确保最后的ACK报文能够到达对方。如果被动关闭方没有收到ACK,会重发FIN报文,TIME_WAIT状态确保有足够时间处理这种重传。
MSL与TTL的关系:
MSL(Maximum Segment Lifetime):报文最大生存时间,Linux设置为30秒
TTL(Time To Live):IP数据报可经过的最大路由数,一般64
MSL应大于等于TTL消耗为0的时间,确保报文自然消亡
TCP可靠传输机制
TCP的可靠传输依赖于多个协同工作的机制:
三次握手与四次挥手:建立可靠的连接基础
序列号与确认应答:保证数据有序性和完整性
超时重传:应对数据包丢失情况
流量控制:通过滑动窗口匹配收发双方的处理能力
拥塞控制:根据网络状况动态调整发送速率
拥塞控制详解
拥塞控制通过拥塞窗口(cwnd) 动态调整发送速率,包含四个核心算法:
慢启动:连接初期指数增长cwnd,每收到一个ACK,cwnd加1
拥塞避免:cwnd超过慢启动门限(ssthresh)后线性增长,每RTT时间cwnd加1
拥塞检测:通过超时重传或重复ACK判断网络拥塞
快速恢复:针对重复ACK的优化,避免过于激进地降低发送速率
滑动窗口机制
滑动窗口实现流量控制,根据接收方缓冲区容量动态调整:
接收窗口(rwnd):接收方告知发送方可用缓冲区大小;
发送窗口(swnd):min(拥塞窗口, 接收窗口);
允许发送方在等待确认时继续发送窗口内的数据,提高带宽利用率。
TCP与UDP对比
特性 | TCP | UDP |
---|---|---|
连接性 | 面向连接 | 无连接 |
可靠性 | 可靠交付 | 尽最大努力交付 |
报文边界 | 无固定边界 | 有明确边界 |
传输效率 | 较低 | 较高 |
首部开销 | 20-60字节 | 8字节 |
适用场景 | 文件传输、网页浏览 | 视频流、DNS查询 |
实际应用问题
TCP粘包问题
由于TCP是流式协议,没有固定报文边界,可能发生粘包现象。解决方案:
固定长度消息:简单但不灵活
特殊分隔符:需注意内容转义
自定义消息结构:包头+数据,包头包含数据长度信息
基于UDP实现可靠传输
虽然UDP本身不可靠,但可以通过上层协议实现可靠性:
QUIC协议:HTTP/3的基础,提供连接迁移、重传机制、前向纠错和拥塞控制。
适用于需要低延迟和高并发连接的场景。
如有问题或建议,欢迎在评论区中留言~