最近面试,问TCP被问住了,感觉背八股背了印象不深刻,还是总结一些比较好。
如果有写错的,欢迎批评指正。
参考:https://www.xiaolincoding.com/network/3_tcp/tcp_interview.html#tcp-%E5%9F%BA%E6%9C%AC%E8%AE%A4%E8%AF%86
目录
TCP的基本概念
TCP:面向连接的、可靠的、基于字节流的传输层通信协议。
TCP连接:socket(IP和端口号)、序列号(解决乱序问题)、窗口大小(流量控制)。
唯一确定TCP连接:源地址、源端口、目标地址、目标端口。
TCP数据包包含的信息:源端口目标端口、序列号确认应答号、ACK/RST/SYN/FIN,首部长度/校验和,窗口大小。
IP层IP数据包最大长度MTU为1500字节。
除去IP和TCP头部外TCP数据的最大长度MSS。
IP层不能重传,只能在TCP层重传,如何在IP层分片,一个分片丢失所有分片都要重传。
TCP的连接建立
- 服务端listen进入LISTEN阶段。
- 第1次握手:客户端发送SYN和序列号,进入SYN_SENT阶段。
- 第2次握手:服务端发送SYN,以及与收到客户端SYN对应的响应ACK,进入SYN_RCVD
- 第3次握手:客户端发送与收到与服务端SYN对应的ACK,进入ESTABLISHED
- 连接成功建立:服务端收到ACK,进入ESTABLISHED
常见问题
为什么要3次握手:
- 阻止历史连接:2次握手,服务端没有中间状态给客户端来阻止历史连接(发出但已经被客户端放弃的SYN,不是相同SYN重传),服务端为已被客户端放弃的旧SYN建立连接,进行第2次握手同时发送数据时,因序列号不符而被客户端RST,就白分配资源和发送数据了。
- 同步双方序列号:4次可以合并为3次。
- 避免重复连接:由于没有第三次握手,服务端不清楚客户端是否收到了自己回复的 ACK 报文,所以服务端每收到一个 SYN 就只能先主动建立一个连接
为什么和如何产生随机序列号?
很大程度上避免被延迟的历史数据报文,序列号落在窗口范围内,被错误的接收;防止黑客伪造相同序列号TCP(?)。
计时器值加连接Hash值。
丢失的处理
- 第1次握手:指数退避超时重传。
- 第2次握手:客户端重传 SYN 报文,服务端重传 SYN-ACK 报文。
- 第3次握手:客户端重传 SYN 报文,单独ACK不会重传。
TCP的连接断开
- 初始时客户端和服务端TCP连接均处于 ESTAVLISHED 阶段。
- 客户端发送 FIN 主动断开连接,客户端进入 FIN_WAIT_1 阶段。
- 服务端收到 FIN ,发送 ACK ,服务端进入 CLOSED_WAIT。
- 客户端收到 ACK ,进入 FIN_WAIT_2 阶段。
- 服务端发送 FIN ,服务端进入 LAST_ACK 阶段。
- 客户端收到 FIN ,发送 ACK ,进入 TIME_WAIT 阶段。
- 服务端收到 ACK ,进入CLOSE阶段。
前两次挥手仅仅表示客户端不再发送数据了,但是还能接收数据。服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文关闭连接。
如果服务端不需要发送数据,可以变成3次挥手。
TIME_WAIT是什么?起到什么作用?
是什么
客户端在收到第3次挥手后,就会进入TIME_WAIT状态,等待 2MSL 后关闭。
如果第4次挥手未送达服务端,服务端会重发第3次挥手,客户端收到时重新计时。
MSL 是报文最大生存时间,任何报文在网络上存在的最长时间,超过时间的报文将被丢弃。
IP层有TTL,是可以经过的最大路由数,经过路由减1,为0时丢弃。MSL应大于TTL减到0的时间。
TTL一般是64,Linux中MSL是30。
2MSL是一来一回的时间上限,相当于允许第4次挥手ACK丢失后,第3次挥手FIN重发一次。
作用
防止历史连接中的数据包被错误接收。
服务端向客户端发送数据,到第3次挥手发出时截止,但之前可能存在被延迟的数据包,等待 2MSL 使数据包从网络中消失,避免当序列号回绕时被之后的相同四元组接收。
确保服务端被正确关闭
第4次挥手的ACK可能没有到达服务端,服务端重发第3次挥手FIN,在TIME_WAIT阶段会再次响应ACK,否则会响应RST。
文章评论