一、ISO7层模型
- 物理层
- 数据链路层
- 网络层
- 传输层 (TCP、UDP)
- 会话层
- 表示层
- 应用层
二、TCP三层(传输层)
2.1 TCP三次握手
建立一个 TCP 连接需要“三次握手” 就能确认双方收发功能都正常, 缺一不可:
- 一次握手:客户端发送带有 SYN(SEQ=x) 标志的数据包 -> 服务端,然后客户端进入 SYN_SEND 状态,等待服务端的确认;
- 二次握手:服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 –> 客户端,然后服务端进入 SYN_RECV 状态。
- 三次握手:客户端发送带有 ACK(ACK=y+1) 标志的数据包 –> 服务端,然后客户端和服务端都进入ESTABLISHED 状态,完成 TCP 三次握手。 其实一旦完成了前两次握手,TCP 协议允许数据在第三次握手时开始传输。如果第三次握手的ACK确认包丢失,但是客户端已经发送了携带数据并且包含ACK标记的包,服务端会将其视为有效的第三次握手确认并正常数据传输。
- 第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常
- 第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常
- 第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常
tcp三次握手过程中内核维护两个队列管理连接请求
半连接队列:服务端收到客户端的syn请求时双方还没有完全建立连接,它会把这种半连接的状态的连接放到半连接队列中
全连接队列:服务端收到客户端ACK相应时意味着三次握手完成,此时服务端会将半连接状态中的该连接移动到全连接队列中。 如果没有收到客户端的ack响应 将会进行重传,重传的等待时间是指数增长的, 如果超出内核配置的最大连接数(tcp_syn_retries、tcp_synack_retries、tcp_retries2),系统将从半连接队列中删除该连接信息。
tcp_syn_retries控制客户端在发起TCP连接时,发送SYN报文的最大重传次数。默认值通常为5。tcp_synack_retries控制服务端在收到客户端的SYN报文后,发送SYN-ACK报文的最大重传次数。默认值通常也为5。
tcp_retries2控制普通数据包在没有收到确认的情况下,TCP层进行重传的最大次数。默认值通常为15
2.2 四次挥手
断开一个 TCP 连接则需要“四次挥手”,缺一不可:
- 第一次挥手:客户端发送一个 FIN(SEQ=x) 标志的数据包->服务端,用来关闭客户端到服务端的数据传送。然后客户端进入 FIN-WAIT-1 状态。
- 第二次挥手:服务端发送一个 ACK (ACK=x+1)标志的数据包->客户端 。然后服务端进入 CLOSE-WAIT 状态,客户端进入 FIN-WAIT-2 状态。
- 第三次挥手:服务端发送一个 FIN (SEQ=y)标志的数据包->客户端,请求关闭连接,然后服务端进入 LAST-ACK 状态。
- 第四次挥手:客户端发送 ACK (ACK=y+1)标志的数据包->服务端,然后客户端进入TIME-WAIT状态,服务端在收到 ACK (ACK=y+1)标志的数据包后进入 CLOSE 状态。此时如果客户端等待 2MSL 后依然没有收到回复,就证明服务端已正常关闭,随后客户端也可以关闭连接了。
第一次挥手:A 说“我没啥要说的了”
第二次挥手:B 回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话
第三次挥手:于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”
第四次挥手:A 回答“知道了”,这样通话才算结束。
2.3 常见问题
为什么不能把服务端发的 ACK 和 FIN 合并起来,变成三次挥手?
因为服务端收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复 ACK,表示接收到了断开连接的请求。等到数据发完之后再发 FIN,断开服务端到客户端的数据传送。
如果第二次挥手时服务端的 ACK 没有送达客户端,会怎样?
客户端没有收到 ACK 确认,会重新发送 FIN 请求。
转载请注明来源, 欢迎对文章中的引用来源进行考证, 欢迎指出任何有错误或不够清晰的表达, 可以邮件至 chinaops666@gmail.com