TCP连接的状态详解以及故障排查(1)(3)
2)Server
当Server端调用socket函数调用时,相当于Server端产生了一个处于Closed状态的监听套接字
Server端调用 bind 操作,将监听套接字与指定的地址和 端口关联,然后又调用listen 函数,系统会为其分配未完成队列和
完成队列,此时的监听套接字可以接受Client的连接,监听套接字状态处于LISTEN状态。
当Server端调用accept操作时,会从完成队列中取出一个已经完成的client连接,同时在server这段会产生一个会话套接字,用于和
client端套接字的通信,这个会话套接字的状态是ESTABLISH。
从图中可以看出,当客户端调用 connect 时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用 accept 函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。
我们可以通过网络抓包的查看具体的流程:
比如我们服务器开启9502的端口。使用tcpdump来抓包:
tcpdump -iany tcp port 9502
然后我们使用 telnet 127.0.0.1 9502开连接.:
telnet 127.0.0.1 9502
14:12:45.104687 IP localhost.39870 > localhost.9502: Flags [S], seq 2927179378, win 32792, options [mss 16396,sackOK,TS val 255474104 ecr 0,nop,wscale 3], length 0 (1)
14:12:45.104701 IP localhost.9502 > localhost.39870: Flags [S.], seq 1721825043, ack 2927179379, win 32768, options [mss 16396,sackOK,TS val 255474104 ecr 255474104,nop,wscale 3], length 0 (2)
14:12:45.104711 IP localhost.39870 > localhost.9502: Flags [.], ack 1, win 4099, options [nop,nop,TS val 255474104 ecr 255474104], length 0 (3)
14:13:01.415407 IP localhost.39870 > localhost.9502: Flags [P.], seq 1:8, ack 1, win 4099, options [nop,nop,TS val 255478182 ecr 255474104], length 7
14:13:01.415432 IP localhost.9502 > localhost.39870: Flags [.], ack 8, win 4096, options [nop,nop,TS val 255478182 ecr 255478182], length 0
14:13:01.415747 IP localhost.9502 > localhost.39870: Flags [P.], seq 1:19, ack 8, win 4096, options [nop,nop,TS val 255478182 ecr 255478182], length 18
14:13:01.415757 IP localhost.39870 > localhost.9502: Flags [.], ack 19, win 4097, options [nop,nop,TS val 255478182 ecr 255478182], length 0
我们看到 (1) (2) (3)三步是建立tcp:
第一次握手:
14:12:45.104687 IP localhost.39870 > localhost.9502: Flags [S], seq 2927179378
客户端 IP localhost.39870 (客户端的端口一般是自动分配的) 向服务器localhost.9502 发送syn包(syn=j)到服务器》
syn的seq= 2927179378
第二次握手:
14:12:45.104701 IP localhost.9502 > localhost.39870: Flags [S.], seq 1721825043, ack 2927179379,
服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包
SYN(ack=j+1)= ack 2927179379 服务器主机SYN包(syn= seq 1721825043)
第三次握手:
14:12:45.104711 IP localhost.39870 > localhost.9502: Flags [.], ack 1,
客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1)
客户端 和 服务器进入ESTABLISHED状态后,可以进行通信数据交互。此时 和accept接口没有关系,即使没有accepte,也进行3次握手完成。
连 接出现连接不上的问题,一般是网路出现问题或者网卡超负荷或者是连接数已经满啦。
紫色背景的部分:
IP localhost.39870 > localhost.9502: Flags [P.], seq 1:8, ack 1, win 4099, options [nop,nop,TS val 255478182 ecr 255474104], length 7
客户端向服务器发送长度为7个字节的数据,
IP localhost.9502 > localhost.39870: Flags [.], ack 8, win 4096, options [nop,nop,TS val 255478182 ecr 255478182], length 0
服务器向客户确认已经收到数据
IP localhost.9502 > localhost.39870: Flags [P.], seq 1:19, ack 8, win 4096, options [nop,nop,TS val 255478182 ecr 255478182], length 18
然后服务器同时向客户端写入数据。
IP localhost.39870 > localhost.9502: Flags [.], ack 19, win 4097, options [nop,nop,TS val 255478182 ecr 255478182], length 0
客户端向服务器确认已经收到数据
这个就是tcp可靠的连接,每次通信都需要对方来确认。
评论暂时关闭