三次握手只有一个目的:就是想让双方都知道对方的发送能力和接收能力是否正常,我先很通俗的解释一下,用甲乙两方举个例子吧~
第一次甲向乙握手成功:乙方知道甲方的发送能力没问题
第二次乙向甲握手成功:“你能向我握手了,我就知道你肯定收到我的前一次握手请求了”,所有甲方知道乙方接收能力,发送能力均正常
第三次握手: 乙方知道甲方的接收能力正常
具体是这样的:
第一次握手:发送请求连接报文,就是一个SYN标志位=1,还要发送一个seq序号,这个seq序号是随机的,是有随机算法的:ISN=M(计时器)+F(端口,IP的四元组),其实这个seq就表示我把我的数据打包好了并且我还给它编了个号X,发送完之后甲方处于SYN_wait状态;
第二次握手:乙方收到这个请求之后,确认应答标志位ACK=1,也会向甲方发送一个请求连接报文(SYN=1)和随机序号(seq=Y),还有一个小ack号=X+1,表示我收到了你序号为X这个数据包了,我希望下次你给我发X+1的包,发送完乙方处于SYN_RCVD状态;
第三次握手:甲方收到了这个请求之后,确认应答标志位ACK=1,发送一个它所期望的seq=x+1给它,还有ack=Y+1,表示我收到你序号为Y的数据包了,我期望你下次发Y+1的包;然后甲方乙方都到ESTAB_lished状态;
这才是真正的三次握手过程,后面就可以进行数据传送了
其实在最开始建立连接之前客户端有一个close状态,服务端有一个listen状态,当我们调用listen这个系统调用之后,就会将一个主动套接字转为被动套接字(监听套接字),服务端和客户端的最重要的区别就是这个。一个服务器只有一个监听套接字,服务器内核会为每一对TCP连接维护一个已连接套接字,就是accept这个API的返回值。
1、调用listen之后会建立SYN和accept两个队列(半连接和全连接)
2、服务器调用accept之后会阻塞,等到accept队列直到有元素
3、客户端调用connect之后,发起SYN请求(一次握手),客户端收到之后会将请求放在SYN队列中,并给客户端回复ACK帧和SYN(二次握手),客户端收到之后返回确认连接的ACK帧给服务器(三次握手),服务器收到之后会将请求从SYN队列中移到accept队列中,这就是三次握手在代码中的体现