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

相关推荐
陈大爷(有低保)13 分钟前
UDP Socket聊天室(Java)
java·网络协议·udp
爱吃涮毛肚的肥肥(暂时吃不了版)18 分钟前
计算机网络34——Windows内存管理
网络·计算机网络·udp
Redstone Monstrosity26 分钟前
字节二面
前端·面试
Adolf_19931 小时前
Flask-JWT-Extended登录验证, 不用自定义
后端·python·flask
码哝小鱼1 小时前
firewalld封禁IP或IP段
linux·网络
叫我:松哥1 小时前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap
海里真的有鱼1 小时前
Spring Boot 项目中整合 RabbitMQ,使用死信队列(Dead Letter Exchange, DLX)实现延迟队列功能
开发语言·后端·rabbitmq
UestcXiye1 小时前
面试算法题精讲:求数组两组数差值和的最大值
面试·数据结构与算法·前后缀分解
严格格2 小时前
三范式,面试重点
数据库·面试·职场和发展
工业甲酰苯胺2 小时前
Spring Boot 整合 MyBatis 的详细步骤(两种方式)
spring boot·后端·mybatis