TCP/IP 与 WebSocket 测试实战:从底层原理到场景落地

前言

在日常测试工作中,我们经常接触 HTTP 接口、WebSocket 长连接、MQTT 消息推送等各种通信场景。这些协议看似独立,实则都建立在 TCP/IP 协议栈之上。搞清楚 TCP/IP 和 WebSocket 的关系,以及它们各自的测试重点,能帮我们在遇到网络超时、连接中断、消息丢失等问题时,更快地定位和推进解决。

本文基于真实项目经验,从测试视角出发,梳理 TCP/IP 和 WebSocket 的测试方法论。不堆砌理论,直接讲清楚"测什么"和"怎么测"。

一、TCP/IP:互联网通信的"地基"

1.1 白话理解

TCP/IP 是互联网通信的基石,核心就两个字:可靠

可以把 TCP 通信理解成一次快递运输

  • 寄件前要先确认收件地址有效(三次握手

  • 包裹太大要拆成多个小包分开发,到了目的地再拼装(拆包/粘包

  • 每个小包都要回执确认收到了,没收到就重发(超时重传

  • 全部签收后正式结束(四次挥手

TCP/IP 保证的是:数据不丢、不乱序、不重复。但代价是有额外的开销(握手、确认、重传),速度相对 HTTP 的长连接轮询要慢一些。

1.2 TCP/IP 测试四维度

在实际项目中,我从四个维度来保障 TCP/IP 层面的通信质量:

维度一:通不通 ------ 连接建立

测试目标:验证 IP/端口可达,三次握手能正常完成。

测试方法

bash

复制代码
# 基础连通性验证
telnet <目标IP> <目标端口>

# 查看当前已建立的连接状态
netstat -ant | grep ESTABLISHED

合格标准telnet 能成功连接,连接状态为 ESTABLISHED

维度二:扛不扛得住 ------ 并发与连接资源

测试目标:高并发场景下,端口资源不耗尽,握手队列不溢出。

核心关注状态

连接状态 含义 风险点
SYN_RECV 服务端收到SYN,等待客户端ACK 半连接队列堆积 → SYN Flood攻击或性能不足
TIME_WAIT 主动关闭方等待2MSL后释放端口 堆积过多 → 本地端口耗尽
CLOSE_WAIT 被动关闭方等待应用层调用close() 持续增长 → 代码存在连接泄漏

测试方法

  1. 使用 JMeter 发起高并发短连接请求(如 5000 并发,总请求数 10 万)

  2. 压测结束后立即执行以下命令:

bash

复制代码
# 检查半连接队列是否溢出
netstat -ant | grep SYN_RECV | wc -l

# 检查服务端是否有连接泄漏
netstat -ant | grep CLOSE_WAIT | wc -l

# 检查客户端端口回收情况
netstat -ant | grep TIME_WAIT | wc -l

合格标准

  • SYN_RECV 在压测结束后快速归零

  • CLOSE_WAIT 数量稳定,不随时间持续上涨

  • TIME_WAIT 数量允许偏高,但应随时间逐渐下降

真实案例 :在成飞中台项目的亿级数据压测中,JMeter 高并发时频繁报错 Cannot assign requested address。通过 netstat 排查发现 TIME_WAIT 堆积超过 1.5 万个,导致本地端口耗尽。解决方案是将 HTTP 请求改为长连接复用(Keep-Alive),TPS 从 500 提升至 2000。

维度三:丢包了咋办 ------ 传输可靠性

测试目标:网络不稳定时,TCP 能否通过超时重传保证数据最终送达。

测试方法

  1. Fiddler 模拟随机丢包 :在 CustomRules.jsOnBeforeRequest 中增加脚本:

javascript

复制代码
// 随机丢弃 10% 的请求包
if (Math.random() < 0.1) {
    oSession.oRequestFlags = SessionFlags.Abort;
}
  1. Wireshark 抓包验证重传 :观察抓包结果中的 TCP Retransmission 标记(通常显示为黑色或高亮),确认 TCP 层确实在自动重传。

  2. 业务层验证:在丢包 10%~20% 的情况下,执行核心业务流程(如订单提交、文件上传),观察最终结果是成功还是卡死。

合格标准

  • 丢包率 ≤ 10%:核心业务应最终成功(依赖 TCP 重传兜底)

  • 丢包率 ≥ 30%:系统应在合理超时后明确报错,不能无限等待

维度四:断线了咋整 ------ 保活与异常恢复

测试目标:空闲连接不被中间设备断开;服务异常崩溃后,客户端能自动恢复。

测试方法

  1. Keep-Alive 空闲保活测试 :客户端建立连接后不做任何操作,静置 1 小时 ,用 netstat 确认连接仍处于 ESTABLISHED 状态。如果连接被 NAT 或防火墙断开,说明需要调整系统 Keep-Alive 参数或在应用层增加心跳。

  2. RST 异常断开测试 :压测过程中直接在服务器上 kill -9 杀掉后端服务进程,观察客户端:

    • 能否触发 onerroronclose 事件

    • 是否在 1~3 秒内启动重连(推荐指数退避策略:1s → 2s → 4s → 8s...)

    • 重连后用户是否需要重新登录

二、WebSocket:在 TCP 之上建立"实时对讲"

2.1 白话理解

WebSocket 是基于 TCP 协议 之上的一种持久双向通信协议 ,核心就两个字:实时

类比一下 HTTP 和 WebSocket 的区别:

  • HTTP 是"写信" :客户端写一封(请求),服务器回一封(响应)。每次都要重新拿信封写地址(携带请求头),而且只能客户端主动问,服务器不能主动说话。

  • WebSocket 是"打电话" :先拨号(HTTP 握手升级),接通后双方随时可以说话。服务器有新数据能立刻"推"给客户端,不需要等客户端来问。后续消息不再带冗长的 HTTP 头,省流量、延迟低。

2.2 WebSocket 的连接流程

text

复制代码
客户端                                服务端
    |                                    |
    |-------- HTTP GET (Upgrade) ------->|  ← ① 握手请求
    |                                    |     (带上 Upgrade: websocket)
    |<------- 101 Switching Protocols ---|  ← ② 协议升级成功
    |                                    |
    |======= WebSocket 全双工通道 ========|  ← ③ 双向通信
    |-------- 数据帧 (客户端发) --------->|
    |<-------- 数据帧 (服务端推送) -------|
    |-------- Ping (心跳) --------------->|
    |<-------- Pong (心跳响应) -----------|
    |-------- Close (关闭帧) ------------>|
    |<-------- Close (关闭帧响应) --------|

2.3 WebSocket 与 TCP/IP 的关系

WebSocket 并不替代 TCP/IP,而是跑在 TCP/IP 之上的一层协议

层级 协议 角色
应用层 WebSocket / HTTP 业务数据格式、消息语义
传输层 TCP 可靠传输、拥塞控制、流量控制
网络层 IP 寻址和路由

换句话说:TCP/IP 保证"数据包能可靠到达",WebSocket 在之上规定了"怎么握手升级、消息长什么样、怎么保持心跳"

三、WebSocket 测试五维度

基于 TCP/IP 的底层测试能力,再加上 WebSocket 独有的上层校验,形成以下五维测试体系:

维度一:握手通不通

测试目标:验证 HTTP 升级请求能否成功切换为 WebSocket 协议。

测试方法

  • 使用 Postman / Apifox 发起 WebSocket 连接请求

  • 检查服务端返回的状态码必须是 101(Switching Protocols)

  • 验证鉴权场景:Token 过期或错误时,应返回 401 或拒绝连接,而不是 101

关键 Headers

text

复制代码
GET /ws/chat HTTP/1.1
Host: example.com
Upgrade: websocket        ← 关键:要求升级
Connection: Upgrade       ← 关键:连接管理
Sec-WebSocket-Key: xxx    ← 握手密钥
Sec-WebSocket-Version: 13 ← 协议版本

维度二:消息发不收得

测试目标:验证 WebSocket 通道建立后,双向消息能否正常收发。

测试要点

测试类型 验证内容
文本消息 普通字符串、JSON 格式数据
二进制消息 图片、文件等二进制数据
消息顺序 连续发送多条,是否按顺序到达(不出现乱序)
消息分片 超大消息是否被拆分成多个帧,接收端能否正确拼装
消息幂等 网络重传是否导致服务端收到重复消息(需业务层去重)

注意:WebSocket 底层基于 TCP 流传输,也会遇到 TCP 粘包/拆包问题。测试时需要验证应用层是否能正确区分消息边界。

维度三:长连接扛不扛得住

测试目标:验证服务器支持的最大并发长连接数。

测试方法

  • 使用 JMeter(需安装 WebSocket Sampler 插件)同时建立 1000、5000、10000 个长连接

  • 观察指标:

    • 服务器内存是否线性增长(每个连接约占用几 KB 内存)

    • 文件句柄数是否接近系统上限(ulimit -n

    • CPU 在空闲连接下的消耗是否正常

与 HTTP 压测的区别

HTTP 压测 WebSocket 压测
关注指标 QPS、响应时间 最大并发连接数、连接内存占用
资源瓶颈 CPU、数据库连接池 文件句柄、内存
连接特征 短连接,用完即关 长连接,持续占用资源

维度四:空闲保活 ------ Ping/Pong 心跳

测试目标:连接闲置时,业务层心跳能否防止被中间设备踢掉。

测试方法

  1. 建立 WebSocket 连接后不做任何操作,静置 30~60 分钟

  2. 通过抓包观察是否有 WebSocket 协议帧(Opcode: 0x9 Ping / 0xA Pong)在定时交互

  3. 确认连接没有被运营商 NAT 或防火墙断开

关键区别

保活机制 层级 默认间隔 测试重点
TCP Keep-Alive 操作系统 TCP 层 通常 7200 秒(2 小时) 系统级配置是否生效
WebSocket Ping/Pong 应用协议层 通常 30~60 秒 业务层是否主动发送心跳帧

即使 TCP Keep-Alive 没开,只要 WebSocket 的 Ping/Pong 正常工作,连接也能保持存活。

维度五:异常断开与自动重连 ------ 续命能力

测试目标:服务端异常崩溃或网络中断时,客户端能否自动恢复连接和业务状态。

测试方法

  1. 服务端崩溃(RST 复位) :直接 kill -9 杀掉 WebSocket 服务进程

  2. 网络中断:拔网线或 Fiddler 模拟断网

  3. 重连验证

    • 客户端能否在 1~3 秒内触发 onerror / onclose 事件

    • 是否按指数退避策略尝试重连(1s → 2s → 4s → 8s,避免风暴)

    • 重连成功后,业务状态是否恢复

      • 用户需要重新登录吗?(理想情况是复用原有 token)

      • 需要重新订阅业务频道/房间吗?(理想情况是自动恢复订阅)

      • 重连期间错过的消息是否有补偿机制(断线重连补偿队列)

真实案例:在圈层查控系统中,我专门模拟了大运会期间检查站 4G 信号闪断的场景,验证了预警推送在 WebSocket 重连后不会丢失,且客户端能自动重新订阅实时布控频道。

四、TCP/IP vs WebSocket 测试对比总结

测试点 TCP/IP 测试 WebSocket 测试 说明
连接建立 三次握手,关注 ESTABLISHED 握手升级,关注 101 状态码 WebSocket 多一层 Upgrade 校验
并发压测 短连接压测,关注 TIME_WAIT 端口回收 长连接压测,关注 内存 + 句柄数 压测模型完全不同
丢包/重传 ✅ 完全一致 ✅ 完全一致 WebSocket 底层走 TCP,重传机制一样
网络中断 ✅ 完全一致 ✅ 完全一致 抓包看 RetransmissionRST
空闲保活 TCP Keep-Alive(操作系统层,默认 2h) Ping/Pong 帧(应用层,通常 30s~60s) 两层独立,WebSocket 必须单独测 Ping/Pong
服务端崩溃 ✅ 完全一致(测 RST 后的重连) ✅ 一致,但多了业务恢复验证(重新登录?重新订阅?) WebSocket 需验证业务上下文恢复

五、常用命令与工具速查

5.1 连接状态查看(Linux / Windows)

bash

复制代码
# 查看所有 TCP 连接状态统计
netstat -ant | awk '{print $6}' | sort | uniq -c

# 查看特定状态的连接数量
netstat -ant | grep CLOSE_WAIT | wc -l
netstat -ant | grep TIME_WAIT | wc -l
netstat -ant | grep SYN_RECV | wc -l

# 查看进程占用的文件句柄数(排查连接泄漏)
lsof -p <PID> | wc -l

5.2 Fiddler 丢包脚本

javascript

复制代码
// CustomRules.js - OnBeforeRequest 中添加
// 随机丢弃 10% 的请求包,模拟网络丢包
if (Math.random() < 0.1) {
    oSession.oRequestFlags = SessionFlags.Abort;
}

5.3 JMeter WebSocket 压测

需要的插件:WebSocket Sampler by Peter Doornbosch(通过 JMeter Plugins Manager 安装)

关键参数设置:

  • Server Name or IP:目标服务器地址

  • Port Number:WebSocket 端口

  • Protocol:ws / wss(加密)

  • Connection Timeout:连接超时时间

  • Read Timeout:读取超时时间

  • Streaming Connection:保持连接持续监听

六、总结

TCP/IP 和 WebSocket 不是二选一的关系,而是地基与建筑的关系

  • TCP/IP 测的是"水管漏不漏水、水压够不够"------关注连接建立、端口资源、丢包重传、断线恢复

  • WebSocket 在 TCP 之上加了三层独有的保障------握手升级(101)、业务心跳(Ping/Pong)、重连后的业务续命

在测试实践中,TCP/IP 的那套工具链(Fiddler 丢包、netstat 看状态、JMeter 压测、Wireshark 抓包)可以直接复用到 WebSocket 的底层测试中,只需要额外补充 WebSocket 特有的握手、心跳、订阅恢复等校验点即可。

掌握这套方法论,无论是测 HTTP 接口、WebSocket 推送,还是 MQTT 物联网通信,都能做到心中有数、手中有招。

相关推荐
名字还没想好☜1 小时前
Next.js Route Handler 做 SSE 服务端推送:实时进度条、自动重连与什么时候别用 WebSocket
开发语言·javascript·websocket·react·sse·next.js
地衣君1 小时前
从 profile 到 kanban:Hermes 多 Agent 协作解析及示例
网络·数据库·tcp/ip
eggrall3 小时前
Socket编程UDP
网络协议·udp·php
g3voip12 小时前
防爆电话如何接入SIP调度系统?工业通信系统架构解析
服务器·tcp/ip·系统架构·信息与通信·ip
bitbrowser20 小时前
MXToolbox检测IP只红一个黑名单时,如何判断?
网络·网络协议·tcp/ip
楷哥爱开发21 小时前
目标国家 IP 会影响 TikTok、Instagram 的内容分发和受众地区吗?
大数据·运维·tcp/ip
智购科技自动贩卖机1 天前
自动售货机硬件主控方案选型实战:单片机、树莓派、ESP32怎么选?
人工智能·单片机·嵌入式硬件·物联网·网络协议·yolo·架构
00后程序员张1 天前
SSL Pinning 抓包抓不到明文?绕过证书固定的几种方案
网络协议·计算机网络·网络安全·ios·adb·https·udp
为思念酝酿的痛1 天前
Socket编程--TCP
服务器·网络·tcp/ip