众所周知,TCP是面向连接的协议,那么建立连接和释放连接就是必不可少的过程。所以在整个数据传输过程中一共分为三个阶段,连接建立、数据传输、连接释放。
三次握手
-
作用
1.确定通信双方都有收发数据的能力
2.通信双方协定一些规则,(进行序号同步,确定双方的接收窗口剩余大小以及单次最大报文字节数等等)
-
握手过程
如同所示,在这里假设连接请求方为客户端A,连接接收方为服务器B,刚开始A处于CLOSED状态,B处于LISTEN状态。- A发送连接请求,同步位SYN置1,初始序号seq置x(这里的seq的值是内核进行动态生成的,以防被攻击),此时客户端A进入SYN_SENT状态。
- 服务端B接收到A的连接请求后,如果同意连接则向A回送应答报文段,把SYN置1,初始序号seq置y,ACK置1,表示确认号有效,ack确认号为x+1,这里的 ack=x+1是因为客户端的SYN报文占一个序号,表示自己已经收到这个报文段,之后服务器B进入SYN_RCVD状态。
- 客户端A接收到B的确认后要向A会送确认,ACK置1,序号seq为x+1,确认序号为y+1(B的报文占一个序号)。此时A进入ESTABLISHED状态,即为通信状态。
- B在收到A的确认报文段后进入ESTABLISHED状态。双方可以进行通信。
-
容易忽略的问题
1.在连接的过程中,数据的交换不止图上的这些,他们还会进行接收窗口剩余大小的确认,还有向对方确认单次最大的数据发送量。2.握手最少是三次,可以理解为握手的目的是确认双方都有数据段收发的能力第一次握手,A知道了自己具有数据发送的能力,第二次握手A知道自己有收发能力,而且B有收发能力,此时B知道了A有发送能力而自己有接收和发送能力,但是不知道A是否有接收能力,等到第三次握手,B收到报文后知道A有发送能力,此时才能进行通信。之所以说最少三次,是因为B在收到A的连接请求后可以先发送ACK确认,然后再进行SYN同步,所以也可以是四次。
3.在三次握手的前两次是不能进行数据传输的,避免造成浪费内核空间,但是第三次握手的时候,A已经进入通信状态,此时可以发送数据。
-
报文丢失问题
如果第二次握手丢失,此时服务端已经进入SYN_RCVD状态,在等待一定时间没有收到客户端的确认请求后,会触发重传机制,从1s、2s、4s、8s-----64s,如果还是没有收到A的确认请求,那么B会发送RTS包断开连接。
如果第三次握手丢失,此时客户端已经进入ESTABLISHED状态,所以认为已经可以传输数据,然后会进行数据包的发送,而服务端没有进入ESTABLISHED状态,在收到A的报文段之后认为是非法的的报文段,会对其发送RST包断开连接。
四次挥手
四次挥手较三次握手来说复杂一点
-
挥手过程
挥手之前通信双方都是ESTABLISHED状态,通信断开可以由任意一方发起(一般由数据发送较快的一方发起),在这里还是假设由客户端发起- 客户端A发送释放连接报文段,FIN置1,发送序号seq=u,然后进入FIN_WAIT_1状态。(这里的seq与上次收到的ack确认号相同)
- 服务端B收到连接释放请求后会发送ACK确认报文,ACK置1,ack确认号为u+1(FIN消耗一个序号),seq符号为v。发送完之后进入CLOSE_WAIT状态。A在接收到该报文段之后进入FIN_WAIT_2状态。
- 此时客户端A处于半连接状态,服务端B继续向发送未发完的数据,直到发送完毕后,向A发送FIN报文段,因为又向A发送了一部分数据,所以此时序号seq变为w,然后B进入LAST_ACK状态,等待A的确认报文段。
- A收到B的FIN报文段后,发送ACK确认报文段,然后进入TIME_WAIT状态,B在收到A的报文段后进入CLOSED状态。
- A在等待2MLS之后进入CLOSED状态。
-
TIME_WAIT存在的原因
1.为了保证A的最后一个报文段能被B接收
如果A在发送完最后一次报文之后直接断开,那么如果B没有收到这次报文,那么就会造成一直处于未关闭状态,造成资源浪费。而使用TIME_WAIT状态后,如果报文丢失,B会触发重传机制,并且重新启动2MLS计时器。
2.防止已失效连接请求报文进入连接中。
这个目的是为了防止在前面的发送的连接请求由于延迟,结果在断开连接之后重新进入连接,而在2MLS之内足够本次连接所有的报文段从网络中消失。 -
容易忽略的问题
1.四次挥手不一定是四次,如果双方的数据都传输完毕,第二三次握手会合成一次
2.四次挥手过程中的数据包丢失都是靠重传机制解决的。
整个连接从开始到结束可以用这个图描述
最后提一下保活计时器,TCP中除了有时间等待计时器,还有保活计时器。主要是用来防止在通信过程中一方出现故障,导致另一方一直在等待数据接收,造成资源的浪费。服务端每收到客户端的一次数据,就会重新设置保活计时器,一般时间是连个小时,之后每隔75s一次,一连10次之后仍无相应,就会关闭连接。
本文章主要是根据读《计算机网络》这本书还参考了别人的博客进行理解最后写下来的,本人小白一枚,如有什么错误欢迎来告知。下一篇文章准备写一下使用netstat查看连接状态的文章,有兴趣可以看一看