一、三次握手
1、第一次握手
客户端发送同步消息(SYN=1,ACK=0,seq=x)到服务器(TCP规定SYN=1时不能携带数据,x为随机产生的一个值),并进入SYN_SEND状态,等待服务器确认。
注:
- SYN(同步):在连接建立时的同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1。故SYN置为1,就表示这是一个连接请求和连接接收报文;
- ACK(确认):当ACK=1时,确认字段才有效。当ACK=0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1;
- seq(Sequence Number):占4个字节。序号使用mod
运算。TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。故该字段也叫做“报文段序号”。
2、第二次握手
服务器收到SYN报文段进行确认,将SYN标识位置为1,ACK置为1,seq置为y,ack置为x+1,然后进入SYN_RECV状态,这个状态被称为半连接状态。
注:
- ack(Acknowledgment Number):是期望收到对方下一个报文段的第一个数据字节的序号。若确认序号=N,则表明:到序号N-1为止的所有数据都已正确收到。
3、第三次握手
客户端再进行一次确认,将ACK置为1,seq置为x+1,ack置为y+1发向服务器,最后客户端与服务器都进入ESTABLISHED状态,完成三次握手,建立连接。
4、为何还需要客户端在第三次握手中再次确认?
若TCP仅采用两次握手的机制,即客户端发出连接请求,服务端确认请求则建立连接。
假设客户端发出一次建立连接请求,因网络堵塞服务端并未收到请求,客户端认为请求丢失再次发送第二次建立连接请求,服务端收到请求并确认,成功建立链接。
而第一个连接请求报文段并没有丢失,只是在某些网络节点长时间滞留了,以至于延误到连接释放以后的某个时间点才到达服务端。本来这个连接请求已经失效了,但是服务端收到此失效的连接请求报文段后,就误认为这是客户端又发出了一次新的连接请求。于是服务端又向客户端发出请求报文段,同意建立连接。
由于现在客户端并没有发出连接建立的请求,因此不会理会服务端的确认,也不会向服务端发送数据,但是服务端却以为新的传输连接已经建立了,并一直等待客户端发来数据,这样服务端的许多资源就这样白白浪费了。
采用三次握手的办法可以防止上述现象的发生。比如在上述的场景下,客户端不向服务端的发出确认请求,服务端由于收不到确认,就知道客户端并没有真正请求建立连接。