1.三次握手
1.1状态机
客户端
SYN_SENT:客户端发送SYN报文段请求建立连接
ESTABLISHED:在收到服务端发来的SYN请求报文以及确认报文后就建立客户端到服务端的连接
服务端
LISTEN:一开始时LISTEN状态,等待客户端的SYN请求
SYN_RCVD:当服务端接收到客户端发来的SYN请求后服务端变为接收状态并发送SYN请求,此时的状态也称为半连接队列
ESTABLISHED:当客户端收到SYN报文并且回复确认报文且服务端收到后建立连接
1.2初始序列号ISN
问题:1.初始序列号是什么产生的?2.为什么是随机值,而不是固定值?
1.初始序列号--->ISN:初始序列号是通过源地址,目的地址,源端口,目的端口和一个随机因子通过哈希算法计算得出的。后续又加入了时间因子
2.出于安全性考虑,如果被知道了初始序列号,那么很容易可以构造出一个在对方窗口内的序列号。从而伪造出TCP报文,实现RCP会话劫持。
拓展:TCP序号绕回问题
*重复序号:当序号绕回后,之前已经使用过的序号可能再次出现,导致接收方错误的将重复的报文段当作新的报文段处理。从而丢弃正常的报文
*延迟确认:因为延迟确认是收到一定数量的数据后才发送,而序号绕回会导致延迟确认的触发时间延后,从而降低数据传输的效率
解决思路:使用时间戳选项来增加序号的有效范围
1.3是否可以使用“两次握手报文”建立连接
采用三次握手形式,不是因为两次握手无法建立连接,而是为了防止已经失效的连接请求报文突然又传送到TCP服务端,从而导致服务端回复信息,建立连接,凭空消耗资源
第一次握手可以证明的是客户端的发送能力正常
第二次握手证明客户端的接收能力正常,且服务端的发送能力正常
如果不进行第三次握手则无法证明客户端的接收能力是否正常
1.4三次握手如何阻止历史连接
*当客户端发送连接建立请求报文后,因为网络阻塞,导致客户端重新发送一个连接建立请求报文,这两个报文的序列号不同(因为为初始序列号)。
*当网络阻塞减小时,可能旧的报文先到达服务端,从而导致服务端回复SYN+ACK报文。此时服务端处于同步已接收状态(SYN-RCVD),但是此时对于客户端而言,服务端回复的报文时错误的报文,因为其确认序列号与客户端将要发送的报文的序列号不匹配,则客户端发送RST报文,断开连接。
*当连接断开,服务端恢复到侦听状态,此时客户端发送的第二个连接请求报文到达。之后,正常建立TCP连接。
*如果是两次握手,那么服务端在收到旧的SYN报文后,会直接进入到连接已建立状态。在该状态意味着已经可以发送数据,可能会存在数据传输。但是又因为此时的连接对于客户端而言是错误的,所以此时服务端传输的数据客户端不会接收。
1.5如果已经建立了连接,但是客户端突然故障,怎么办?
*TCP设计了一个保活计时器
*如果客户端出现故障,服务端不能一直等待下去,因为会白白浪费资源
服务端没收到一次客户端的请求后都会复位保活计时器,当保活计时器为0时,服务端主动发送探测报文。并每隔75s发送一次。如果连续十次报文都没有接收到对端回复,则服务端认为客户端出现故障,关闭连接
2.四次挥手
2.1状态机
四次挥手客户端与服务端的状态机
客户端
FIN_WAIT1:客户端的第一个状态---发送FIN标志位
FIN_WAIT2:客户端的第二个状态---在接受完服务端的确认报文段后,等待服务端发送完数据的状态,如果服务端已发送完数据即可等服务端发送FIN标志位的报文段进入TIME_WAIT
TIME_WAIT:客户端的倒数第二个状态---在等待2MSL时间以后,客户端切换状态,进入关闭状态。MSL时最长报文段寿命。默认建议时间为2分钟
CLOSE:当等待完2MSL后客户端都没有收到来自服务端的FIN重发报文段即可关闭
服务端
CLOSE_WAIT:服务端的第一个状态---在收到客户端发送的FIN后处于半关闭状态,客户端到服务端的连接释放断开,服务端给客户端发送确认FIN的报文,有数据就携带数据,无数据则发送第三次挥手报文段
LAST_ACK:服务端的倒数第二个状态,在服务端发送完数据后此时就发送FIN报文
CLOSE:当服务端收到FIN的确认报文后即可关闭
2.2为什么不能是三次挥手
因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。此时如果服务端还有数据未发送完只能先发送一个带有数据的ACK报文,知道数据发送完毕,才发送FIN报文,因此不能是三次挥手
2.3四次挥手释放连接时,等待2MSL的意义?
MSL,可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
3《TCP/IP详解 卷1》TCP变迁图
以下为一张TCP状态变迁图,很具有代表性,有助于大家理解三次握手和四次挥手的状态变化