一、三次握手
Three-way Handshake,其实就是建立TCP连接时,需要客户端和服务器总共发送3个包。主要作用是:确认双方的接受能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传输作准备。实质上就是连接服务器指定端口,建立TCP连接,并同步双方的序列号和确认号,交换TCP窗口大小信息
客户端connect阻塞、服务端accept阻塞时,进行三次握手:
第一次握手:客户端给服务端发一个SYN报文,并指明客户端的初始化序列号ISN-------此时客户端处于SYN_SENT状态
首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序列号
第二次握手:(服务端收到客户端的SYN报文后),以自己的SYN报文作为应答ACK(对方发送的序列号+1),再指定自己的初始化序列号ISN-----此时服务端处于SYN_RCVD状态
确认报文段中:SYN=1,ACK=1,ack=x+1,seq=y
第三次握手:(客户端收到服务端的SYN报文后),也发送一个ACK,再发送一个序列号
确认报文段中:ACK=1,seq=x+1,ack=y+1
ACK报文是用来应答的,SYN报文是用来同步的
1.为什么需要三次握手?两次不行吗?
因为为了确认双方的发送、接受能力都正常,第二次握手后只是确认了客户端的发送、服务端的接收、发送都没问题,还需一次握手确认客户端的接收能力
2.SYN(Initial Sequence Number)是固定的吗?
ISN随时间而变化,因此每次握手(连接)都将具有不同的ISN。ISN可以看作是一个32比特的计数器,每4ms加1 。如果ISN固定,建立的服务器很容易被攻击
3.三次握手过程中可以携带数据吗?
可以,但第一次、第二次握手不可以携带数据
原因是:假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据,会让服务器花费很多时间、内存空间来接收这些报文
对于第三次握手时,客户端已处于ESTABLISHED状态,对客户端而言,他已经建立起连接了,并且他知道服务端能正常接收和发送,所以携带数据也没什么问题
二、四次挥手
Four-way Handshake,建立一个连接需要三次握手,而终止一个连接需要四次挥手(也很形象,客户端或服务端都可主动发起)。这由TCP的半关闭(half-close)造成,所谓的半关闭就是TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力
socket编程中,任何一方执行close()操作即可产生挥手操作
刚开始双方都处于ESTABLISHED状态,假设客户端发起挥手:
第一次挥手:客户端发送一个FIN报文、指定一个序列号------此时客户端处于FIN_WAIT1(终止等待1状态),等待服务端确认
FIN=1,seq=u
第二次挥手:(服务端收到FIN后)发送ACK报文(对方序列号+1)、发送自己的序列号-----服务端进入CLOSE_WAIT
ACK=1,ack=u+1,seq=v
第三次挥手:如果服务端也想断开连接,和客户端发起挥手一样,只不过它会发出连续报文段----服务端进入LAST_ACK(最后确认)
FIN=1,ACK=1,seq=w(新序列号),ack=u+1(没变)
第四次挥手:(客户端收到FIN后)一样发送ACK报文(对方序列号+1)、发送自己的序列号---客户端处于TIME_WAIT状态(TCP未释放掉,经过等待计时器设置的时间后,才进入CLOSED)
ACK=1,seq=u+1(没懂!),ack=w+1
1.挥手为什么需要四次?
当服务端收到FIN报文时,很可能并不会立即关闭SOCKET(还有其他客户端连接中),所以只能先回复一个ACK报文,告诉客户端,“你发的FIN报文我收到了”。
因为服务器不可能因为某个客户端断开连接,就关闭所有客户端的连接
2.四次挥手释放连接时,等待2MSL的意义?
为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失
MSL是Maximum Segment Lifetime的英文缩写,可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃