seq(序号) ack(确认号)
三次握手:
1.Client(客户端)将标志位SYN置为1,随机产生一个值seq=x,并将该数据包发送给Server(服务器),Client进入SYN_SENT状态,等待Server确认。
2.Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=x+1,随机产生一个值seq=y,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态
3.Client收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack = y+1,并将该数据包发送给Server,Server检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
四次挥手:
TCP连接是全双工的(可以同时进行信号的双向传输),因此,每个方向都必须单独进行关闭。这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的两节,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
1.数据传输结束后,客户端的应用进程发出连接释放报文段,并停止发送数据,客户端进入FIN_WAIT_1状态,此时客户端依然可以接收服务器发送来的数据。
2.服务器收到FIN后,发送一个ACK给客户端,确认序号为收到的序号+1,服务器进入CLOSE_WAIT状态。客户端进入FIN_WAIT_2状态。
3.当服务器没有数据要发送时,服务器发送一个FIN报文,此时服务器进入LAST_ACK状态,等
待客户端的确认
4.客户端收到服务器的FIN报文后,给服务器发送一个ACK报文,确认序列号为收到的序列号+1.此时客户端进入
TIME_WAIT状态,等待2MSL(MSL:报文段最大生存时间),然后关闭连接。
三次握手的原因:
三次握手可以防止已经失效的连接请求报文突然又传输到服务器端导致的服务器资源浪费。例如,客户端先发送了一个SYN,但是由于网络阻塞,该SYN数据包在某个节点长期滞留,然后客户端又重传SYN数据包并正确建立TCP连接,然后传输完数据后关闭该连接。该连接释放后失效的SYN数据包才达到服务器端,在二次握手的前提下,服务器会认为这是客户端发起的又一次请求,然后发送SYN,并且在服务器端创建socket套接字,一直等待客户端发送数据,但是由于客户端并没有发起新的请求,所以会丢弃服务端的SYN。此时服务器会一直等待客户端发送数据从而造成资源浪费。
四次挥手的原因(不懂):
由于连接的关闭控制权在应用层,所以被动关闭的一方在接收到FIN包时,TCP协议栈会直接发送一个ACK确认包,优先关闭一端的通信,然后通知应用层,由应用层决定什么时候发送FIN包。应用层可以使用系统调用函数read==0来判断对端是否关闭连接。
TCP握手为什么两次不可以?为什么不用四次?
两次不可以:TCP是全双工通信,两次握手只能确定单向数据链路是可以通信的,并不能保证反向的通信正常。
不用四次:本来握手和挥手一样需要确认两个方向都能联通,本来应该是
1. 客户端发送SYN0给服务器
2.服务器收到SYN0,回复ack(SYN0+1)
3.服务器发送SYN1
4.客户端收到SYN1,回复ACK(SYN1+1)
因为TCP是全双工的,上边的四部确认了数据在两个方向上都可以正确到达,但是2、3步可以合并起来一起发送,加快握手效率,于是变成了三次握手。