小林coding计网-TCP篇

Mr.ZhaoAbout 5 min

1. 三次握手、四次挥手

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

为什么是三次握手:

  1. 避免历史连接:如果因为宕机重发,最好在「被动发起方」建立连接前阻止历史连接,就不会资源浪费,而这样就需要三次握手
  2. 同步双方初始序列号:序列号作用:不重复、不丢弃、按序传输
  3. 避免资源浪费:服务端每收到一个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攻击避免方式:

  1. 修改Linux内核参数,控制队列大小和队满处理方式
  2. tcp_syncokies方法。半连接队列满了后,新收到的SYN包计算出cookie值,返回给客户端;再收到客户端的应答报文时,检查合法性后直接放入全连接队列
小林coding计网-TCP篇03.png
小林coding计网-TCP篇03.png

为什么需要四次?

假设客户端主动关闭连接,客户端发送FIN时,仅仅表示客户端不发数据了,但还能接收数据。服务端可能还有数据处理发送,待不再发送时,才回FIN给客户端

第一次挥手丢失了,发生什么? 重传第一次挥手FIN报文,最大次数由tcp_orphan_retries决定;超过最大次数后再等待两倍时间就会断开

第二次挥手丢失了,发生什么? 重传第一次挥手FIN报文(ACK报文是不会重传的)。对于调用close关闭的连接,60秒内没有收到FIN报文,主动关闭方就会关闭连接

第三次挥手丢失了,发生什么? 和第一次挥手丢失后有些类似,重传并等待第四次挥手,超过参数后断开连接

第四次挥手丢失了,发生什么? 重传第三次挥手FIN报文。客户端接收到 FIN 后发送 ACK ,进入TIME_WAIT状态并等待2MSL 的时间。如果在 2MSL 时间内,因为客户端的 ACK 没有传输到服务端,客户端又接收到了服务端重发的 FIN 报文,那么 2MSL 时间将重新计时

为什么需要TIME_WAIT?

  1. 2MSL的时间足以让原来连接的数据包都自然消失,防止历史连接数据被相同四元组错误连接接收
  2. 保证正确关闭。如果没有2MSL,客户端直接CLOSE,如果服务端再向已关闭的客户端发送FIN报文,客户端会回 RST 报文,不属于正常关闭了
客户端TIME_WAIT过多服务端TIME_WAIT过多
危害占用端口资源,很难和目的IP + Port 一样的服务器建立连接,但只要是不同的服务器还是可以重复使用的因为服务器只监听一个端口,不会导致端口资源受限;但是会占用系统资源,比如fd、内存、CPU等
TCP客户端出现故障服务端出现故障
建立连接后socket设置SO_KEEPALIVE启动保活机制,定时检测客户端故障造成的死亡连接服务端会发送FIN和客户端进行挥手