TCP连接的状态详解以及故障排查(三)

TCP连接建立三次握手

TCP是一个面向连接的协议,所以在连接双方发送数据之前,都需要首先建立一条连接。

Client连接Server

当Client端调用socket函数调用时,相当于Client端产生了一个处于Closed状态的套接字。

(1)第一次握手:Client端又调用connect函数调用,系统为Client随机分配一个端口,连同传入connect中的参数(Server的IP和端口),这就形成了一个连接四元组,客户端发送一个带SYN标志的TCP报文到服务器。

这是三次握手过程中的报文1。connect调用让Client端的socket处于SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

(2)第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

(3) 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户器和客务器进入ESTABLISHED状态,完成三次握手。连接已经可以进行读写操作。

一个完整的三次握手也就是:请求----应答----再次确认。

TCP协议通过三个报文段完成连接的建立,这个过程称为三次握手(three-way handshake),过程如下图所示。

对应的函数接口:

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开连接:

我们看到 (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可靠的连接,每次通信都需要对方来确认。

相关推荐
云手机掌柜16 分钟前
从0到500账号管理:亚矩阵云手机多开组队与虚拟定位实战指南
数据结构·线性代数·网络安全·容器·智能手机·矩阵·云计算
paopaokaka_luck2 小时前
基于Spring Boot+Vue的吉他社团系统设计和实现(协同过滤算法)
java·vue.js·spring boot·后端·spring
Flobby5292 小时前
Go语言新手村:轻松理解变量、常量和枚举用法
开发语言·后端·golang
Warren983 小时前
Java Stream流的使用
java·开发语言·windows·spring boot·后端·python·硬件工程
程序视点4 小时前
IObit Uninstaller Pro专业卸载,免激活版本,卸载清理注册表,彻底告别软件残留
前端·windows·后端
一只小bit4 小时前
Linux网络:阿里云轻量级应用服务器配置防火墙模板开放端口
linux·网络·阿里云
xidianhuihui4 小时前
go install报错: should be v0 or v1, not v2问题解决
开发语言·后端·golang
帽儿山的枪手5 小时前
HVV期间,如何使用SSH隧道绕过内外网隔离限制?
linux·网络协议·安全
上海云盾商务经理杨杨5 小时前
2025数字藏品安全保卫战:高防CDN如何成为NFT应用的“隐形护甲”?
安全·网络安全
爱分享的程序员6 小时前
前端面试专栏-前沿技术:30.跨端开发技术(React Native、Flutter)
前端·javascript·面试