TCP建立连接流程
- 首先客户端向服务器发送请求连接报文段,报文首部同步位SYN=1,同时选择一个初始序列号 seq=x此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
- TCP服务端收到请求报文后,如果同意连接,则发出确认报文段,。确认报文中应该ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号** seq=y**,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
- TCP客户端进程收到确认后,还要向服务器发出确认报文。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
此时,双发就进入了连接状态,可以进行数据传输了。
确认位ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
同步位SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;
序号seq,TCP连接中传送的字节流中的每个字节都按顺序编号,例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始;
确认号ack,若确认号=n,则表明到序号n-1为止的所有数据都已正确接收,期望接收序号为n的数据。
为什么要进行三次握手?
首先要明白:
- 第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常
- 第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常
但此时Server还不能确认自己发送是否正常,需要第三次握手
- 第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常
三次握手检测了双方收发消息的能力
,少一次都不行
还可以防止已经失效的连接请求报文突然又传送到了服务器
,从而产生错误:
如下图,我们采用二次握手方式:
经过一次连接和释放连接后,此时双方都处于关闭状态。但若此之间,网络中滞留了TCP客户端请求连接,这时,滞留连接又到达了服务器,经过两次握手,服务器端就可进入到了连接以建立状态,就会一直等待TCP客户端发送请求资源,但此时TCP客户端是处于关闭状态的,所以一直不会请求服务端,这就造成了服务端的资源浪费。
但若采用三次握手,就可避免这种情况:
经过两次握手后,客户端由于是关闭状态,不会发送确认报文请求。服务端也就进入不了连接已建立状态。
第 2 次握手传回了 ACK,为什么还要传回 SYN?
服务端传回ACK 是对客户端发送的带有SYN标志的请求报文的确认,这表明从客户端到服务端的通信是正常的。而回传 SYN 则是为了让客户端对该条请求连接报文,进行确认,也就是保证从服务端到客户端的通信是正常的。
确认位ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
同步位SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;