首先,是需要明白一些字段的含义,这样三次握手、四次握手的流程图就立马可以很轻松地理解,并迅速手绘了。
(至于这两个流程图,网上铺天盖地都是,这里就不贴出来了。)
SYN:该字段被设置为1(即true),表示请求建立连接
FIN:该字段被设置为1(即true),表示请求关闭连接
seq:该字段为请求序列号,譬如为seq=x, 能够标示一个请求包,在众多包种区分其身份
ack:该字段为确认字段,譬如ack=x+1,表示已经收到对方发来的seq=x的请求包。
然后TCP是个可以双向通信的协议,
一次 “请求连接——确认”操作,可以确保一方做好了发送准备,另一方做好了接收准备,因此可以建议一个单向的连接;
一次 “请求关闭——确认”操作,可以确保一方发完了数据希望关闭发送,另一方收到请求关闭接收,最后关闭掉一个单向的连接。
其实,无论是建立连接的过程,还是关闭连接的过程,实际上都由两个单向连接的 建立过程/关闭过程组成的,也就是在逻辑流程上都可以认为是两个二次握手,即都需要四次。只不过,三次握手中,服务端确认客户端连接的那个过程,即是第一次单向连接的确认,又是第二次单向连接的请求,它把两次交互合并成了一次,因此就变成了三次握手。
(至于说三次握手单纯是因为避免这种情况:客户端过去已经发送的请求,再次到达服务端,导致再次建立连接,而客户端对此无应答,因此导致服务端资源白白浪费。这应该不是根本原因,因为每个请求包都有seq序列号呀,序列号相同的请求包再次到达,在协议设计上,完全可以用seq判断出是否是已经过时的请求包。)
一、建立TCP连接:三次握手协议
客户端:我要对你讲话,你能听到吗;
服务端:我能听到;而且我也要对你讲话,你能听到吗;
客户端:我也能听到。
…….
互相开始通话
……..
二:关闭TCP连接:四次握手协议
客户端:我说完了,我要闭嘴了;
服务端:我收到请求,我要闭耳朵了;
(客户端收到这个确认,于是安心地闭嘴了。)
…….
服务端还没倾诉完自己的故事,于是继续唠唠叨叨向客户端说了半天,直到说完为止
…….
服务端:我说完了,我也要闭嘴了;
客户端:我收到请求,我要闭耳朵了;(事实上,客户端为了保证这个确认包成功送达,等待了两个最大报文生命周期后,才闭上耳朵。)
(服务端收到这个确认,于是安心地闭嘴了。)
#.客户端收到请求包后,为什么要等待两个最大报文生命周期后,才闭上耳朵呢?
为了以防万一,因为最后一个发往服务端B的确认包有可能丢失。若丢失,服务端这里过了响应超时时间timeOut,会再次往客户端A发送关闭连接请求,这时候客户端得保证自己还没闭上耳朵,还能接收请求才行。