三次握手
字段 含义 (大写表示标志位,值为1或0 小写表示序号)
- URG 紧急指针是否有效。为1,表示某一位需要被优先处理
- ACK 确认号是否有效,一般置为1。
- PSH 提示接收端应用程序立即从TCP缓冲区把数据读走。
- RST 对方要求重新建立连接,复位。
- SYN 请求建立连接,并在其序列号的字段进行序列号的初始值设定。建立连接,设置为1
- FIN 希望断开连接。
- seq 序列号 ,随机生成。
- ack 确认号,随机生成 。
盗用一张网上的图片

初始状态:客户端A和[服务器]B均处于CLOSED状态,然后服务器B创建socket,调用监听接口使得服务器处于LISTEN状态,等待客户端连接。
第一次握手:A发送SYN=1、序列号 seq=x 的包请求建立连接,并进入SYN_SENT状态;
第二次握手:B收到连接请求后,同意建立连接,向A发送确认数据,这时TCP头部中的SYN和ACK标识位值均为1,确认序号为ack=x+1,然后选定自己的初始序号seq=y(一般是随机的),确认消息发送后,B进入SYN_RCVD状态;
第三次握手:A收到B的确认信息后,发送确认数据:ACK=1,确认序列号ack=y+1 ,自己的序列号在连接请求的序列号上加1,即seq=x+1,发送完毕后,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
第三次握手是为了防止:A迟迟没有收到B返回的确认报文,这时A会放弃本次连接,重新启动一条连接,但问题是:B不知道A没收到,所以他会收到两个连接请求,造成浪费。
概括一下如下:
1:A告诉B:我要给你发数据了
2:B回复A:收到,你可以给我发数据了,并询问A,我能给你发数据吗
3:A回复B:你也可以给我发数据了,我要开始给你发数据了
A和B都可以发送并接收数据,这样就可以开始通信了。
四次挥手

初始状态:客户端A和服务器B之间已经建立了TCP连接,并且数据发送完成,打算断开连接,此时客户端A和服务器B都可以发送断开请求,下面以A主动发起断开请求为例。 第一次挥手:A发送FIN=1,seq = m请求断开连接,m为A前面正常发送数据最后一个字节序号+1得到的,消息发送后A进入FNI_WAIT_1状态; 第二次挥手:B收到了A的断开请求,并且给A回复一条确认信息ACK=1,自己的序列号为seq=n,确认序列号ack=m+1,n为前面正常发送数据最后一个字节序号+1得到,然后进入CLOSE_WAIT状态,此时A——>B的连接就已经断开。此时,A就进入FIN-WAIT-2(终止等待2)状态,等待B发送连接释放报文(在这之前还需要接受B发送的最后的数据); 第三次挥手:B给A发送完数据结束之后,给A发送确认关闭消息:ACK=1,FIN=1,确认序列号ack=m+1,自己的序列号为w,此时,B就进入了LAST-ACK(最后确认)状态,等待A的最后确认。 第四次挥手:A收到B的消息后,发出确认 ACK=1,序列号为第一次挥手的序列号+1即:seq=m+1,确认序列号ack=w+1,此时,A就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后没有收到B的重传请求,则表明B收到了自己的确认,进入CLOSED状态。B只要收到了A发出的确认,立即进入CLOSED状态。这样,就结束了这次的TCP连接。
可以看到,服务器结束TCP连接的时间要比客户端早一些。
概括一下如下:
1:A告诉B:我要断开了 A发送FIN=1
2:B回复A:好的我知道了,我这边还有点数据,等我发给你 B回复ACK=1
3:B回复A:我的数据发送完了 B回复 ACK=1 FIN=1
4:A告诉B:好的 我知道了 A发送ACK=1,并进入TIME-WAIT状态
A等待2∗∗MSL,保证B收到了消息,B收到后立即进入CLOSED,否则A重说一次”我知道了”,A进入CLOSED。
为什么是三次握手,四次挥手?
主要是在服务端,建立连接时,服务端收到连接报文后可以直接确认报文加发送数据,而关闭连接时,服务端收到FIN报文时,只是收到了,并不会立即关闭,所以只能先回复ACK,再回复FIN,所以需要四次挥手。
为什么需要经过2∗∗MSL(最长报文段寿命)的时间?
按理来说,四个报文发送完毕就可以进入CLOSED状态了,但是网络是不可靠的,有可能最后一个ACK丢失。2∗∗MSL就是一个发送和一个回复所需的最大时间。如果直到2∗∗MSL,客户端都没有再次收到FIN,那么客户端就推断ACK已经被成功接收,则结束TCP连接。