TCP协议–三次握手与四次挥手
TCP协议的格式:
TCP协议的格式:
端口:源端口/目的端口 负责端与端直接数据传输
序号 确认序号:进行包序管理
长度:头部长度,以四字节为单位,表示TCP头部最少20字节,最大60字节
标志位:
URG:紧急指针是否有效。为1,表示某一位需要被优先处理
ACK:确认号是否有效,一般置为1.
PSH:提示接收端应用程序立即从TCP缓冲区把数据读走。
RST:对方要求重新建立连接,复位。
SYN:请求建立连接,并在其序列号的字段进行序列号的初始值设定,建立连接,设置为1。
FIN:希望断开连接
窗口大小:用于避免丢包的一种方式
校验和:校验数据一致性
紧急指针:带外数据
选项数据:通常用于通信双方协商一些信息的时候使用
三次握手图示
第一次握手:客户端发送syn包(seq = x)到服务器,并进入SYN_SENT状态等待服务端确认;SYN:表示同步序列编号。
第二次握手:服务端收到syn包,确认客户的SYN(ack = x + 1),同时也发送一个SYN包(seq = y),就是SYN + ACk包,此时服务端进入SYN-RCVD状态。
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack = y + 1),这个包就发送完毕,客户端和服务端都进入ESTAB-LISHED状态(TCP连接成功),完成三次握手。
常见关于三次握手的问题
为什么握手协议要进行三次
两次客户端只能确定服务端,但是服务端不能确定客户端是否在线,不太安全,必须都要确保对方都有收发数据的能力。
客户端发送SYN请求之后,万一退出来,这时候服务端不进行再一次确认的话,就会丢包。
如果第一次SYN因为网络延迟于后发的第二个SYN同时到来,会造成服务端创建多余的socket。
ACK+SYN两个一起发送,避免发送两次相同的头部信息。
四次挥手图示
TCP连接释放过程
1)客户端的应用进程先向其TCP发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1(终止等待1)状态,等待B的确认。
2)服务器收到连接释放报文段后即发出确认报文段,(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE-WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。
3)客户端收到服务端的确认后,进入FIN-WAIT-2(终止等待2)状态,等待服务端发出的连接释放报文段。
4)服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),B进入LAST-ACK(最后确认)状态,等待A的确认。
5)客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME-WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。
有关四次挥手常见问题
一、挥手为什么为四次,不是三次
1、套接字的关闭有多种操作shutdown(fd,SHUT_RD/WR),可以分别关闭套接字的读和写
而其中当关闭套接字写操作,会触发向对端发送FIN包,接收方收到Fin之后,认为对方不在继续发送数据,
因此recv会返回0,等待用户套接字关闭(close_wait),关闭套接字则会向对方发送FIN
2、在发送端要是只关闭写端,并没有关闭套接字读端,意味着对方有可能还在发送数据,自己有可能还需要接受,
因此ACK和FIN不能一起发送,否则自己在有些数据还没有接收成功的情况下收到了FIN,则会造成数据没有处理完毕,
或者对端数据没有发送完毕,因此不能挥手三次
(2)TIME_WAIT有什么用
1、假设主动关闭,没有这个等待时间,而是直接关闭套接字,有可能使用相同的地址信息启动新的客户端
2、若前边一个ACK走失,对端重发FIN
3、新启动的客户端有可能就会收到FIN包,对新连接造成影响
4、新的客户端会向服务端发送SYN就会被认为状态错误,重置连接,因此主动关闭发送方最后一个ACk之后必须等待一段时间
(1)在等待期间,收到重发的FIN包就可以重新回复一次ACK
(2)等待一段时间,是等待本次通信所有数据都消失在网路之中,避免对后续连接造成影响,因此等待时间是两个MSL(报文的最大生命周期)时间