先说句实在话,很多朋友的电脑上会同时装着 Charles、Fiddler、Wireshark、Postman 这四个工具,但真到排查问题的时候,往往是这个打开看一眼、那个抓一把包,最后也没理清楚到底该用哪个、怎么配合。我自己刚入行那会儿也是这样,四个工具全装齐了,却经常在 Fiddler 和 Charles 之间反复横跳,Wireshark 打开之后看着满屏的包发懵,Postman 只会拿来做最简单的 GET 请求。这篇文章我就把这四个工具的使用边界、核心操作和配合思路一次讲透,争取让看完的人能直接上手干活。
先说结论:它们看起来都和“接口”有关,但解决的问题并不一样。Charles 和 Fiddler 是 HTTP/HTTPS 抓包调试工具,面向应用层,适合看请求和响应内容、改包、做弱网模拟;Wireshark 是网络协议分析工具,工作在更底层,适合看 TCP 三次握手、排查连接不通、分析重传和延迟;Postman 则是接口测试工具,核心价值在于构造请求、管理用例、做断言校验。把这层分工搞清楚了,后面所有操作才不会白费。
1. 四款工具的分工边界:先搞清它们到底解决什么问题
很多新手最大的困惑不是某个工具不会用,而是不知道什么场景该用哪个。我见过有人用 Wireshark 去抓 HTTPS 请求内容,结果解不开密,回头骂工具不好用;也有人用 Postman 去测线上接口连通性,测半天发现根本没法模拟 App 的完整签名逻辑。这不是工具的问题,是没分清它们各自的层次。
1.1 抓包工具与接口测试工具的层次差异
这四个工具大致可以分成三个层次:
- 应用层调试层:Charles 和 Fiddler。它们以 HTTP 代理的形式工作,App 或浏览器的请求先经过它们,再由它们转发给服务器。你能看到完整的请求头、请求体、响应头、响应体,还能打断点修改请求或响应。这一层关注的是“接口的内容对不对”。
- 协议层分析层:Wireshark。它直接抓取网卡上的数据包,工作在 IP、TCP、UDP 这一层。你能看到 SYN、ACK、FIN 的交互过程,能看到 DNS 解析耗时,能看到 TCP 重传和乱序。这一层关注的是“网络通不通、慢在哪”。
- 接口测试层:Postman。它本身不抓包,而是主动向服务器发起请求,适合做接口调试、自动化测试、环境切换。你可以把接口用例组织成集合,写断言、跑批量回归。这一层关注的是“接口在给定输入下返回是否符合预期”。
打个比方:Charles 和 Fiddler 像是监控收银台的录像,能看清每一笔交易的细节;Wireshark 像是物流公司全程的车辆轨迹,能看出货在哪个路段堵了;Postman 则像是你自己去柜台办理业务,测试柜员按某种规则处理你的表单。
1.2 什么时候该用哪个工具:一张实战选型表
我自己这些年用下来的选型逻辑,基本上可以浓缩成下面这张表:
| 场景 | 首选工具 | 为什么 |
|---|---|---|
| App 接口请求内容不对、参数可疑 | Charles 或 Fiddler | 能直接看加密后的 HTTPS 明文内容 |
| 某个接口偶尔超时、想确认耗时分布 | Charles 或 Fiddler | 有请求耗时时间线,能区分是网络还是后端处理慢 |
| 线上域名通不通、TCP 握手是否成功 | Wireshark | 能看到完整的连接建立过程,判断问题在网络层 |
| 怀疑运营商或局域网丢包、延迟大 | Wireshark | 看 TCP 重传率、RTT 变化 |
| 后端联调、构造请求、调试入参 | Postman | 最方便地构建各类请求体、管理环境变量 |
| 批量回归接口、做自动化测试 | Postman + Newman | 集合管理和数据驱动能力强 |
| 修改接口响应来测试 App 异常分支 | Charles 的 Map Local / Rewrite | 是我用过最顺手的改包方案 |
| 弱网环境模拟、测试超时重试逻辑 | Charles 的 Throttle | 限速设置直观,Fiddler 也支持但稍繁琐 |
说一个很容易踩的坑:Charles 和 Fiddler 只能看到经过代理的 HTTP/HTTPS 流量,TCP 层的问题它们是看不到的。有些 App 不走系统代理(比如部分长连接、部分推送通道),这时你用 Charles 会发现抓不到请求,但不代表流量没发生。这种时候就该切到 Wireshark 去抓网卡流量确认连接是否存在。我遇到过多次这类问题,最后都是靠 Wireshark 定位到是连接根本没建立,而不是应用层的问题。
2. Charles 和 Fiddler:HTTP 抓包的日常姿势与核心操作
这两款工具定位几乎一致,选哪个更多是习惯问题。我用 Charles 比较多,但 Fiddler 的某些场景也有优势。下面把最核心的几套操作分别讲透。
2.1 代理配置与手机抓包:Charles 实操
先说 Charles 的启动使用。安装后默认代理端口是 8888,启动时它会自动配好系统代理。要抓本机浏览器的请求,直接打开即可,基本零配置。
手机抓包的步骤要稍微注意:
- 电脑和手机连同一个局域网。
- 在 Charles 菜单栏选择 Proxy -> Proxy Settings,确认 HTTP Proxy 勾选且端口为 8888。
- 手机上设置 Wi-Fi 代理,服务器填电脑的局域网 IP(如 192.168.1.100),端口填 8888。
- 此时 Charles 会弹出一个提示框,询问是否允许来自该 IP 的连接,点 Allow。
- 手机访问 http://chls.pro/ssl 下载并安装 Charles 的 SSL 证书,iOS 还需要在“设置 -> 通用 -> 关于本机 -> 证书信任设置”中信任该证书。
这里最容易被卡住的一个点是:配置好了代理但手机完全无法上网,基本只有两个原因——代理 IP 填错,或者 Charles 的 Allow 弹窗被误点了 Deny。前者去电脑的“系统偏好设置 -> 网络”里确认 IP,后者在 Charles 的 Proxy 菜单里把当前 IP 移除再重新抓一次。
Android 7.0 之后有个特殊限制:默认情况下,App 只信任系统证书,用户安装的 Charles 证书是无效的。所以你会遇到“浏览器能抓包、App 抓不到明文”的情况。要解决只有两种思路:一是让开发在 App 的网络安全配置里加上 debug 环境的 trust-anchor,二是用系统证书的方式安装(需要 root 或刷入证书模块)。在写这篇内容前我建议优先找开发配合在 debug 包中放开证书信任,否则把时间耗在证书上很不划算。
HTTPS 解密的配置在 Charles 中也很直观。路径是 Proxy -> SSL Proxying Settings,勾选 Enable SSL Proxying,然后添加 Host 和 Port。如果不关心具体域名,直接填*和443即可。但我不建议长期这样开着,因为解密所有 HTTPS 流量会明显增加 CPU 负载,而且 Charles 日志会变得异常杂乱。更推荐的做法是只针对需要调试的域名开启解密,比如添加api.example.com:443。
2.2 断点修改与重放:Fiddler 与 Charles 的实际用法
改包是接口调试中非常高频的需求。比如后端返回的钱数是分,你想测试 App 在金额异常时是否会给出提示,直接改响应比让后端改代码要快得多。
Charles 改包分两种:
- 改请求:右键请求 -> Breakpoints,然后在请求尚未到达服务器前修改参数。比如把商品数量从 1 改成 100,看后端是否正确校验。
- 改响应:同样先给请求设置 Breakpoints,但在返回阶段修改响应体内容,App 这边拿到的就是你改过的数据。
Fiddler 的对应操作是:在 QuickExec 命令行输入bpu加 URL 片段来设置请求断点,或者用 AutoResponder 功能把某个请求直接重定向到本地文件或固定返回。AutoResponder 比 Charles 的 Map Local 在某些场景下更灵活,因为它还支持修改响应状态码。
我还经常用 Charles 的Map Local来做前端联调。做法是:右键一个 JS 或接口请求,选择 Map Local,然后在本地指定一个文件路径,之后所有匹配的请求都会直接从本地文件读取,不再访问服务器。这个功能在调试前端静态资源时特别省事,不用每次改完代码都重新部署一遍。
Fiddler 还有一个 Charles 没有的优势:它内置了 Composer,可以直接编辑并重放请求。不过这个问题不大,因为重放这种事情用 Postman 来做更顺手,后面会专门讲。
2.3 限速与弱网模拟:让测试提前暴露问题
弱网模拟是我非常推荐每个人都要掌握的功能。很多线上问题都是因为开发在强网环境下写代码,没考虑到弱网下的超时和重试逻辑。如果你能在测试阶段就模拟出 3G 甚至 2G 的网络环境,很多崩溃问题可以提前暴露。
Charles 的操作是:Proxy -> Throttle Settings,勾选 Enable Throttling,然后在预设模板里选择 56 kbps 或 3G。你还可以自己设置带宽、延迟时间、丢包率(在 Charles 里叫 Bit Rate、Latency、Loss %)。这里我一般把丢包率设为 1%~2%,延迟设为 150~300ms,这样更贴近真实弱网场景。
Fiddler 对应的是 Rules -> Performances -> Simulate Modem Speeds,默认模拟的是 56k 猫的网速,如果想自定义,需要写脚本来实现。相比之下 Charles 的图形化配置更友好,所以我个人的习惯是弱网模拟优先选 Charles。
但要注意:限速只对经过代理的请求生效。如果 App 某些流量不走代理,限速就形同虚设。所以测弱网时我会先用抓包确认请求确实经过了代理,再开限速。
2.4 过滤与定位:抓包时如何从一堆请求里快速找到目标
解决了一个关键问题:当手机连上 Charles 后,里面那个列表每秒都可能新增几十上百条请求,怎么定位到想要的接口?
我的操作习惯是三步:
- 在左下角的 Filter 输入框里输入目标 API 的关键路径片段,比如
login或order。 - 如果有必要,可以结合左上方的 Structure 视图按域名收起展开,先找到目标域名,再逐级下钻。
- 右键目标请求,选择 Focus,把这条请求置顶并高亮,方便后续持续观察。
Fiddler 的过滤逻辑稍有不同,是通过底部的 Filters 标签页勾选规则,比如只显示某个 Host 的流量、隐藏静态资源(图片、CSS、JS)等。我更推荐用Left,在 Fiddler 的 Host 列右键选择 Host 过滤,操作更快更准。
还有一个很实用的技巧:在 Charles 里,找到目标请求后直接右键 -> Copy cURL Request,再把 cURL 命令贴到 Postman 里导入,Postman 会自动帮你解析好 Method、URL、Headers、Body,省去手动填写的功夫。这一步是串起抓包工具与接口测试工具的关键桥梁。
3. Wireshark:当问题下沉到网络层时的排查思路
前面说过,Charles 和 Fiddler 解决的是应用层问题,但有些问题必须下沉到网络层才能看清。比如连接建立不了、TCP 重传率高、数据包乱序、DNS 解析超时等等。这时候 Wireshark 才是正确答案。
3.1 过滤器的正确打开方式:抓包过滤器与显示过滤器要分清
Wireshark 的过滤器有两大类,搞混了会出现“我明明设置了条件,为什么还是抓到一堆包”的情况。
- 抓包过滤器(Capture Filter):在开始抓包前设置,直接决定网卡捕获哪些包,不满足条件的包根本不会进入缓存。这是对磁盘写入和内存的提前裁剪。
- 显示过滤器(Display Filter):在抓包结束后设置,对已捕获的数据包列表做过滤,只影响显示,不影响原始数据。
比如我想抓某台服务器 IP 为192.168.1.50的请求:
- 抓包过滤器写:
host 192.168.1.50,注意是 BPF 语法,不支持and写成&&。 - 显示过滤器写:
ip.addr == 192.168.1.50,用在顶部过滤栏。
日常习惯上,我很少设置抓包过滤器去限制条件,因为一旦条件写错或过于严格,容易错过关键包。我通常先全量抓,然后用显示过滤器逐步缩小范围,反正现在的电脑内存和磁盘都足够宽裕。只有在抓大流量场景如全链路压测时才会用抓包过滤器来裁剪。
常用的显示过滤器我整理了一份:
| 目标 | 显示过滤器语句 |
|---|---|
| 某台主机的全部流量 | ip.addr == 192.168.1.50 |
| 某个端口的流量 | tcp.port == 443 |
| 只看 HTTP 明文请求 | http |
| 只看 DNS 请求 | dns |
| 找出 TCP 重传的包 | tcp.analysis.retransmission |
| 找 SYN 握手包 | tcp.flags.syn == 1 && tcp.flags.ack == 0 |
| 只看 HTTPS 握手过程 | tls.handshake.type == 1 |
3.2 用 Wireshark 看一次完整请求的时间消耗分布
有一次我和某同事排查一个线上接口为什么间歇性变慢,后端日志显示处理只需要 30ms,但客户端感知却超过 1 秒。初期用 Charles 看,只能看到请求发出到收到响应是 1.2 秒,无法进一步定位。后来用 Wireshark 抓包,把 DNS、TCP 握手、TLS 握手、HTTP 请求、响应返回这几个环节的耗时拆开,才看清问题出在 TCP 重传上。
一个完整的 HTTPS 请求在 Wireshark 里通常能拆成这几段:
- DNS 解析:找到域名对应的 A 记录。
- TCP 三次握手:SYN、SYN-ACK、ACK。
- TLS 握手:ClientHello、ServerHello、证书协商等。
- HTTP 请求发送:客户端发出 GET/POST。
- HTTP 响应返回:服务器把响应数据回传。
在 Wireshark 里选中一个 HTTP 请求包,点击右键 -> Follow -> HTTP Stream,可以看到这次请求的完整来龙去脉。如果要看时间开销,着重点在于:
- 选中第一个 SYN 包,查看包列表底部“Time since first frame”或当前包与上一个包的时间间隔。
- 在 Statistics -> TCP Stream Graph -> Time-Sequence Graph(Stevens)中观察整体传输节奏,异常陡峭或停顿的区间往往是慢的根源。
那次排查的结论是:网络中间链路确实存在 TCP 重传,导致 TLS 握手阶段发出 ClientHello 后迟迟等不到 ServerHello,最终表现为接口偶发超时。这个判断在 Charles 的视图中是完全无法得出的。
3.3 Wireshark 的进阶操作:Export Objects 与 I/O Graph
还有两个功能我用的频率很高,可能很多初学者还没接触过。
第一个是File -> Export Objects -> HTTP。它会把经过该网卡的 HTTP 响应内容按资源类型列出来,你可以直接把图片、JS、JSON 响应导出保存。这个功能在取证和调试静态资源是否被篡改时特别有用。比如怀疑某个 CDN 节点返回了错误的旧版 JS,直接在 Wireshark 里导出响应内容和正常环境对比,效率很高。
第二个是Statistics -> I/O Graph。它可以把你关注的流量绘制成折线图,通过时间维度观察流量峰谷和异常波动。比如你想确认某段网络是否周期性拥塞,把过滤条件设为ip.addr == x && tcp.analysis.retransmission,看重传包是否集中在某几个时间段。图上能直观判断规律。
这里需要额外提醒一句:Wireshark 能抓报文的网卡不一定是目标流量的路径。比如你在电脑上开 Wireshark,但抓包对象是手机,那手机流量必须经由该电脑转发或在同一台交换机的镜像口才能被看到。很多人直接开着 Wireshark 用手机访问,结果什么都抓不到,原因就在这里。如果你的诉求是抓手机流量,首选 Charles/Fiddler;如果一定要用 Wireshark,需要设置好 WiFi 代理到电脑,或借助支持镜像抓包的交换机。
4. Postman:从单接口调试到自动化用例设计的完整思路
Postman 的定位和前三者完全不同。它不干扰流量,而是主动构造请求。它的核心能力是接口测试的组织和自动化:环境管理、集合管理、断言脚本、批量执行。
4.1 环境变量与动态参数:解决多环境切换的痛点
刚开始用 Postman 的人最容易犯的错是:在 URL 里硬编码域名和参数。比如http://192.168.1.50:8080/api/login。一旦要切到测试环境或生产环境,就得手动改一大片。
正确做法是用环境变量:
- 点击 Postman 右上角的眼睛图标,选择 Manage Environments。
- 创建两个环境:
dev和test。在 dev 中设置base_url = http://192.168.1.50:8080,在 test 中设置base_url = http://test.example.com。 - URL 写成
{{base_url}}/api/login。 - 用右上角的环境下拉框切换。
在此基础上还可以配置全局变量(Globals),比如全局的timeout = 5000或公共请求头里的固定字段。环境变量和全局变量的优先级是:环境变量覆盖全局变量。
动态参数是另一个高频需求。比如每次请求的timestamp都不同,或者登录接口需要先算出签名。Postman 支持在请求中用{{$timestamp}}这类动态变量,个人觉得还是要和脚本配合更顺手。具体做法在下一节讲。
4.2 前置脚本与断言脚本:把测试从“手动点”变成“自动验”
Postman 的脚本分两块:Pre-request Script(请求前执行)和Tests(请求后执行)。它们本质上是运行在沙箱里的 JavaScript,可以访问pm对象。
最常见的用法是:
- 在 Pre-request Script 里生成签名或 token。
- 在 Tests 里校验响应结果,并把后续要用的变量回写到环境变量中。
举个实际例子:假设登录接口的响应里有access_token,后续其他接口都要带这个 token。我的处理是:
在登录接口的 Tests 里写:
pm.test("登录成功且返回 token", function() { const resp = pm.response.json(); pm.expect(resp.code).to.eql(0); pm.expect(resp.data.access_token).to.not.be.empty; pm.environment.set("access_token", resp.data.access_token); });在后续接口的请求头中,直接把 Authorization 写成Bearer {{access_token}}。这样只要先跑登录,后面的接口就自动带上 token,完全不用手动复制。
再比如某些接口要求请求体里有一个 sign 字段,基于其他参数拼接后 MD5 加密得到。在 Pre-request Script 里可以这样写:
const timestamp = Math.floor(Date.now() / 1000); const appKey = "test_app_key"; const rawString = `appKey=${appKey}×tamp=${timestamp}`; const sign = CryptoJS.MD5(rawString).toString(); // Postman 内置 CryptoJS pm.variables.set("timestamp", timestamp); pm.variables.set("sign", sign);这样每次发请求时,sign 都自动生成,不会因为参数过期被后端拒绝。这是我做接口自动化时最常用的套路。
4.3 集合自动化与数据驱动:跑一批用例而不是一条一条点
当接口用例多了,把它们组织成一个 Collection,然后用 Runner 一次性批量执行,是 Postman 最有生产力的功能。
组织方式建议按业务模块建集合,在集合下面再建子目录。比如:
- 用户模块
- 登录
- 获取用户信息
- 修改密码
- 订单模块
- 创建订单
- 取消订单
- 查询订单列表
每个请求都要有对应的测试断言,这样批量跑的时候能自动判活。
Runner 里还有一个很强大的功能是数据文件(Data File)。你可以准备一个 JSON 或 CSV 文件,每行代表一组测试数据,Runner 会按行迭代执行同一个请求。
比如测登录接口,准备一个login_data.csv:
username,password,expectedCode test_user_1,123456,0 test_user_2,wrong_pass,1001在请求体的用户名和密码处使用{{username}}、{{password}},在 Tests 里断言:
pm.test("返回预期的业务码", function() { const resp = pm.response.json(); pm.expect(resp.code).to.eql(parseInt(pm.variables.get("expectedCode"))); });跑一次 Runner 就能把所有登录用例覆盖到。这样看似简单的功能,配合 CI 里的 Newman 执行,基本就是一个轻量级接口自动化回归方案了。
对决要在真实环境验证,我建议平时就把断言写扎实。断言不要只检查状态码为 200,要检查业务码、关键字段的值、响应时间是否符合预期。
4.4 从 Charles 导入请求:抓包与测试的衔接
最后说一个非常实用的衔接操作。很多时候我们不是在 Postman 里从头开始写请求,而是先在 Charles/Fiddler 里抓到真实的请求,然后把它导入 Postman 变成可复用的用例。
Charles 的做法前面提过,右键 -> Copy cURL Request。Postman 这边操作是:
- 点击 Import。
- 选择 Raw Text,粘贴刚才复制的内容。
- Postman 会自动生成一个请求,包含 Method、URL、Headers、Body。
Fiddler 也可以:在抓到请求后,右键 -> Copy -> Just Headers(只复制请求头),再配合复制请求体的内容粘贴到 Postman。不过那会比较麻烦,还得手动填 Body。Charles 的 cURL 导出一句解决,我是更喜欢这步用 Charles。
导入之后,建议立刻做两件事:把 URL 中的硬编码地址替换为环境变量,把 token 之类的动态依赖用变量替代。否则这个用例换个环境就废掉了。这一步做得好,你的接口用例库会越来越丰富,而不是每次都在手工敲请求。
5. 四工具联动的完整排障链路:一个真实场景走一遍
工具单独讲容易,但真正体现价值的是在一段完整的排查流程中,它们如何接力配合。我拿一个典型的“App 某接口偶发卡顿”问题来串一遍。
5.1 第一步:Postman 确认接口自身没有功能性缺陷
现象是 App 里有一个订单列表接口偶发加载很慢,有时要 5 到 8 秒,有时又很快。
我不会直接上抓包工具,而是先在 Postman 里构造同样的请求,连续跑 20 次,观察是否有稳定复现。如果 Postman 里响应也慢,说明问题大概率在后端或网络链路;如果 Postman 里很快,那问题可能出在 App 的请求构造、代理链路或本机网络设置上。
实测下来,Postman 里响应时间基本在 100ms 以内。说明接口本身正常,问题出在 App 环境或网络链路上。
5.2 第二步:Charles 看请求内容与耗时分布
接着在 Charles 里抓 App 的请求,找到订单列表接口,查看右下角的 Timing 面板,里面会显示你请求各阶段的耗时:
- Request Start
- Request Body
- TTFB(首字节到达时间)
- Download
当时看到的情况是 TTFB 偶尔飙到好几秒。TTFB 高说明服务器处理或者网络传输存在瓶颈。这一步先把问题圈定在了“从请求发出到收到首个响应字节”的区间。
再仔细看几个慢请求的请求头,发现 Authorization token 都正常,请求体也没问题,基本排除因参数错误导致后端处理延迟。于是问题进一步缩小到网络链路层。
5.3 第三步:Wireshark 定位连接层细节
因为问题发生在 TTFB 之前,我是用 Wireshark 抓包来确认:TCP 连接建立是否正常?TLS 握手是否二次超时?是否发生重传?
抓包后发现:慢的请求都出现了TCP 重传,而且集中在 TLS 握手阶段。ClientHello 发出去后,服务器端的 ServerHello 没有及时收到,客户端超时重发了一遍,导致整个建链过程被拉长了 1 到 2 个 RTT。重传一多,TTFB 自然就上去了。
再用 Wireshark 的 I/O Graph 把重传包按时间画出来,发现重传集中在某个固定网段的 IP 上,基本锁定了是特定链路的问题。这已经不是应用层能解决的,需要网络团队在中间链路上排查。
5.4 第四步:回到 Charles 验证修复效果
网络团队调整了路由策略后,我再用 Charles 抓同样的接口,确认 TTFB 恢复正常,再用 Postman 连续跑 50 次,看耗时分布是否趋于稳定。
最终还是用 Postman 的 Runner 做了一轮简单回归,确保多个接口都没有因为网络链路调整而出现新问题。
整个过程看下来,四个工具缺一不可:
- Postman 首先证明了应用层功能没问题。
- Charles 定位了问题在“发出请求到首字节返回”的区间。
- Wireshark 进一步定位到 TCP 层重传这个根因。
- 最后再回到 Charles 和 Postman 验证修复结果。
这也是我最想传达的思维方式:接口工具不是用来对比哪个更好用的,它们是不同层面的眼睛,拼在一起才构成完整的排障能力。
6. 高频踩坑记录:代理冲突、证书失效、过滤器误用
最后把几个我反复踩过的坑集中说一说。这些东西单独看都很小,但在关键时刻耗费的时间往往是最多的。
6.1 代理冲突:Charles 抓不到包,Fiddler 也连不上
一套典型的现象是:Charles 开着,Fiddler 再启动,结果发现两者都收不到请求,或者浏览器直接提示代理连接失败。
原因很简单:Charles 和 Fiddler 本质都是本地代理,默认都会抢占系统代理设置。如果两者同时运行,一个把代理设成 8888,另一个把代理设成 8888 或 8888,会互相覆盖,导致流量混乱。
我的建议是:
- 同一时间只开一个抓包代理工具。
- 端口避免冲突,Charles 用 8888,Fiddler 用 8888 或改成 8888。
- 如果 Fiddler 和 Charles 习惯都保留,实在需要切换,先退出一个再开另一个。
另外,如果你用了系统代理的软件或本地开发代理工具,也可能会和 Charles/Fiddler 产生冲突。遇到“明明开了代理但抓不到包”时,先检查系统代理设置到底被谁改写了。在 macOS 上可以看“网络设置”里的代理;在 Windows 上是“Internet 选项 -> 连接 -> 局域网设置”。
6.2 手机连上代理后无法上网或抓不到包
这个我前面提了一部分,这里再展开说。最常见的原因是:
- 代理 IP 填错。电脑的 IP 不是查出来的,要在系统的网络设置里看实际分配的 IP。
- 手机和电脑不在同一网段。比如手机连了 5G Wi-Fi,电脑插了网线走另一个网段。
- Charles 的 Allow 弹窗没点允许,或误点了 Deny。
- 证书没装或没信任。iOS 还要额外在证书信任设置里打开开关。
另外,如果 App 不走系统代理,怎么配代理都抓不到。这时先用浏览器访问一个网址试试,如果浏览器能抓、App 不能抓,说明是 App 本身不走代理或证书不被信任。如果是 App 不走代理,我就考虑用它自己的调试模式,或临时让网络层把流量指向代理,而不是在 Charles 里死磕。
6.3 Wireshark 过滤误用:明明有包,显示过滤器却是空的
这是 Wireshark 新手最常踩的坑。抓包过程中,列表最下面提示有多少包被捕获,但顶部过滤栏一输入条件,列表就空了。
大概率是写错了过滤语法。比如把ip.addr = 192.168.1.50写成单等号。Wireshark 的显示过滤器用的是==而非=,写错后 Wireshark 会把输入当作无效表达式,直接清空列表。
还有一种是无法区分显示过滤器和抓包过滤器。如果在 Capture Options 里写死了port 80,那么即使顶部显示过滤器写成tcp.port == 443,也是看不到任何 443 端口的包的,因为抓包阶段已经过滤掉了。这又回到了 3.1 节说的两种过滤器的区别。
6.4 Postman 环境变量作用域混乱导致请求发错环境
Postman 的变量有 Global、Environment、Collection、Local 四层作用域,优先级从低到高是 Global < Environment < Collection < Local。我见过有人在一个环境的变量里设了base_url,另一个环境里忘了设,结果全局变量里残留了一个旧域名,浪费了很多时间。
建议养成两个习惯:
- 每个环境都完整地创建自己的变量,不要依赖全局变量里的兜底值。
- 请求发出去之前,先看 URL 高亮部分是否已经正确解析成了实际的地址。Postman 对未解析的变量会用红色或特殊样式标出,留意这一点可以避免很多低级错误。
6.5 证书信任链问题汇总
证书问题是最折磨人的一个系列,我把几种常见情况和对应处理写在一个表里:
| 现象 | 原因 | 处理方式 |
|---|---|---|
| 浏览器提示证书无效 | 未在系统钥匙串中信任 Charles/Fiddler 证书 | 重新安装证书并信任 |
| iOS 中 Charles 显示 CONNECT 但看不到内容 | 未开启 SSL Proxying | 在 SSL Proxying Settings 添加目标域名 |
| Android 中浏览器能解密,App 解密失败 | App 只信任系统证书 | 开发在 debug 包中开放信任,或使用系统证书方案 |
| 手机上看点证书下载页面打不开 | 代理没生效 | 检查代理 IP 和端口,确保手机能访问chls.pro/ssl |
每次换电脑或重装系统后,都要重新把证书完整装一遍,这一步忘掉是最浪费时间的。
6.6 小经验:别忽略了抓包工具的性能开销
最后分享一个很多人没意识到的事:Charles 和 Fiddler 开启 HTTPS 解密以后,会明显增加 CPU 占用,特别是在大流量场景下,可能影响本机应用的表现,甚至让你误判为网络问题。所以我一般在确认只需要看明文请求的时候才开启 SSL Proxying,否则默认只抓 HTTP,这样既能减少干扰,又能降低资源消耗。
如果你发现 Charles 越来越卡,可以先检查是不是把*:443全部解密了。改成只解密实际要调试的域名,很多奇怪的卡顿会消失。
7. 写在最后:用工具的思路比工具本身更重要
回顾一遍这四个工具,我真正想表达的是:查接口问题时的第一件事不是打开工具,而是先搞清楚问题可能出在哪一层。先判断是应用层、网络层还是接口功能性故障,再决定用哪个工具、以什么顺序排查。用 Charles 看内容,用 Wireshark 看链路,用 Postman 验证功能,三者配合才能高效解决实际问题。
平时我也建议把工具的默认配置做一次彻底调校:Charles 只保留必要的 SSL 解密域名、Fiddler 的根证书时间检查关掉、Wireshark 的显示过滤器预设常用几个模板、Postman 把环境变量和集合目录整理规范。这些一次性投入不会浪费,后续每次都受益。
最后分享一个实用小习惯:我会在每个项目开始时花 5 分钟把 Postman 集合目录结构和环境变量建好,把 Charles 的 SSL 解密域名配好,再在 Wireshark 里存几条项目专用的显示过滤器。看起来是慢了一小步,但在后面很长一段时间里,每一次排查都会快一大截。磨刀不误砍柴工,这套流程值得每个人去执行。