TCP连接和各状态浅析
TCP连接和各状态浅析 TCP协议中三次握手连接和四次挥手断开和其中的状态变化 TCP(Transmission Control Protocol)协议在OSI模型中属于传输层的协议(第4层)也是最常用的互联网协议,与UDP相比它是一种可靠的传输协议,建立和断开连接中一共有11种可能发生的状态(states)。 Linux系统中可以用ss -nat命令查看所有TCP连接情况如果是旧的系统没有此命令可以使用netstat代替只是输出格式不一致,统计当前所有TCP状态可以加管道实现 ss -nat | awk 'NR>1 { d[$1]++ } END { for (i in d) print i, d[i] }' 建立连接(三次握手) TCP是面向连接的所以传输双方在传输前要建立一条连接后才能通信,建立连接后TCP协议提供全双⼯(就是可以同时发送和接收不影响)的通信服务。建立连接的过程我们给它取了个生动的名字叫“三次握手”,因为从发起到建立连接一共有三个步骤也就是双方会发三个包,先看下面的图 首先客户端发送SYN(Synchronous)包到服务端告诉服务器开始建立连接,包里面会包含一个随机数(j)序列号(Sequence Number),此时客户端进入SYC-SENT状态。当然最初服务器是处于LISTEN状态监听某一个端口,本文图片以绿底黑框的都代表TCP状态。 服务端收到SYN发送应答SYN-ACK(Acknowledgement)携带确认号码(Acknowledge Number)为收到的序列号+1也就是j+1,加上一个自己的SYC序列号随机数(k),服务端把状态置为SYN-RECEIVED 客户端收到SYN-ACK包并发送确认号码k+1,此时客户端的状态为ESTABLISHED,服务器收到ACK后状态也变为ESTABLISHED 以下是wireshake抓包后TCP连接的三次握手,这里序列号码j和k都为0。 TCP A (port 65525) TCP B (port 443) LISTEN (Start) 1. SYN-SENT --> <SEQ=0><CTL=SYN> --> SYN-RECEIVE 2. ESTABLISHED <-- <SEQ=0><ACK=1><CTL=SYN,ACK> <-- SYN-RECEIVE 3. ESTABLISHED --> <SEQ=1><ACK=1><CTL=ACK> --< ESTABLISHED 断开连接(四次挥手) 断开连接称为“挥手”一共有四步每一方向占两步,由于TCP是全双工的所以关闭连接需要双方都完成关闭(close)才算结束,其中会涉及状态也就比握手多。客户端和服务端都可以发起挥手动作,先发送FIN包的动作叫主动关闭(active close)然后另一方回应ACK包叫执行被动关闭(passive colse),双方各完成一次主动和被动关闭一共四次。 客户端数据传输完毕发起断开连接(主动关闭),发送FIN包携带一个序列号(x)到服务端并更新自己的状态为FIN-WAIT-1 服务端收到FIN包返回ACK包(被动关闭),应答ACK确认序号为x+1,服务端此时的状态为CLOSE-WAIT。另一边客户端收到ACK更新状态为FIN-WAIT-2 服务端准备执行断开连接(主动关闭),此时服务端的状态还是CLOSE-WAIT,发送FIN包携带序列号(y)到客户端更新服务端状态为LAST-ACK,客户端收到FIN包后状态变为TIME-WAIT。 客户端收到FIN应答ACK(被动关闭)携带确认序号为y+1,服务端收到ACK立即关闭连接状态变为CLOSED 因为客户端最后不知道服务端有没有收到ACK包,所以默认等待两倍的MSL(Maximum Segment Lifetime),Linux上MSL一般为60s,等待120s使服务器如果没有收到ACK也能重传FIN包,最后把自己的状态置为CLOSED在此之前的MSL时间中一直是TIME-WAIT状态 看一个现实中的例子ssh连接退出...