面霸之路——TCP的三次握手与TCP的四次挥手
TCP Flags(TCP报文头的标志位)
URG:紧急指针标志
为1时,表示紧急指针有效,为0则忽略紧急指针
ACK:确认序号标志
为1时,表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段
PSH:push标志
为1表示带有push标志的数据,通知接收方在接收到数据报文段后应尽快将报文段交给应用程序,而不是在缓冲区排队
RST:重置连接标志
用于重置由于主机崩溃或者其他出现错误的连接或者用于拒绝非法的报文段和数据连接请求
SYN:同步序号,用于建立连接过程
SYN=1和ACK=0表示该数据段没有使用捎带的数据域,SYN=1和ACK=1表示使用捎带的数据域
FIN:finish标志,用于释放连接
为1时表示发送方已经没有数据发送了,即关闭本方数据流
TCP的三次握手
当一个应用程序希望通过TCP与另一个应用程序通信时,他会发送一个通信请求,这个请求必须被发送到一个确切的地址,在双方握手之后,TCP将在俩个应用程序之间建立一个全双工的通信,通信将占用俩个应用程序之间的通信线路。直到它被一方或双方关闭为止。(全双工就是说计算机A可以给B发送信息,在发送信息的同时,B也能给A回发信息)
“握手”是为了建立连接,TCP的三次握手流程图如下:
第一次握手:最开始假设A和B首次进行通信,开始的时候都处于CLOSED的状态,假设主动打开连接的是客户端,被动打开的是服务端,刚开始的TCP服务进程先创建传输控制块TCB,时刻准备接受客户端进程发过来的请求,此时服务端进入LISTEN,即监听的状态,此时客户端进程也是先创建一个传输控制块TCB,然后向服务器发出连接请求报文,这就是我们报文头里的TCP Flags中的同步序号SYN=1,同时选择一个初始序号seq=x,x可以是任意的正整数值,此时客户端进程进入一个SYN-SENT同步已发送状态,发过去的包称为SYN报文段,是不携带数据的,但会消耗一个序号,这就是第一次握手;
第二次握手:当服务器接收到请求报文之后,如果同意连接,则发出确认报文,其中包含TCP Flags中的俩个字段,一个是ACK=1,一个是SYN=1,而确认号是x+1原因是之前在SYN报文中指定seq=x,作为回应要回应与x相关的信息,又由于报文消耗掉一个序号,所以ack为x+1,同时也要为自己的缓存初始化一个序列号seq=y,此时服务端进入一个SYN-RCVD,即同步接收状态,此时报文也不携带数据,同样也要消耗掉一个序号,这就是第二次握手;
第三次握手:当TCP客户进程收到确认报文之后,还要向服务器给出一个确认,确认报文的ACK=1,此时ack=y+1,自己的序号就是seq=x+1,此时TCP连接建立,客户端就进入了ESTABLISHED,即已建立连接的状态,TCP规定这个报文段可以携带数据,这就是第三次握手,当服务器收到客户端的确认信息之后,也会进入ESTABLISHED状态,此后双方就可以通信了。
如果大家想要细致入微地了解三次握手,可以使用Wireshark工具进行抓包操作。
TCP的四次挥手
四次挥手即终止TCP连接,断开一个TCP连接时需要客户端与服务端总共发出四个包,以完成连接的断开,在socket编程中,这一过程由客户端或服务端任一方执行CLOSE来触发,我们假设由客户端主动触发CLOSE。
“挥手”是为了终止连接,TCP四次挥手的流程图如下:
第一次挥手:数据传送完毕之后,双方都可释放连接,最开始的时候客户端和服务端都处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。首先,客户端进程发出连接释放报文,并且停止发送数据,在报文头中FIN=1,假设客户端定义的序列号为seq=u,该值等于前面ESTABLISHED状态下数据最后一次发送时已经传送过来的数据的最后一个字节的序号加上1,此时客户端进入FIN-WAIT-1终止等待状态。
第二次挥手:当服务器收到连接释放报文之后也要发出确认报文即ACK=1作为回应,回值时u要加1,即ack的seq=u+1,并且也要携带上自己的序列号,即seq=v,此时服务端进入CLOSED-WAIT关闭等待状态,此时服务端处于半关闭的状态,如果发送数据给客户端还是能接收的,持续时间为CLOSE-WAIT状态所持续的时间,客户端收到服务端的终止请求后,进入FIN-WAIT-2,即终止等待-2状态,等待服务器发送释放连接报文。
第三次挥手:假设服务器将最后的数据发送完毕,就会向客户端发送连接释放报文,就是FIN=1,ack还是等于u+1,由于在半关闭的状态,服务器很有可能又发送了数据,假定此时的序号已经变为w,此时服务器就进入了LAST-ACK状态,即最后的确认状态,等待客户端的最终确认。
第四次挥手:客户端在收到服务器的连接报文之后,必须发出确认即ACK=1,将服务器发过来的w变为w+1通过ack回发过去,此时自己的序号为u+1,之后客户端进入TIME-WAIT,即时间等待状态,注意此时TCP连接还没有释放,必须经过2MSL(MSL即最长报文段寿命,RFC793中规定MSL的值为2min,LINUX设置成了30s)的时间后连接才能真正的释放进入CLOSED状态,而服务器只要收到了客户端发出的确认,立即进入CLOSED状态,服务器结束TCP的连接时间要比客户端要早一些。