树莓派智能摄像头系统 30 天重学计划之 Day 03 · 网络基础:建立“包“的思维 —— 学习总结

所属计划:智能摄像头 30 天路线图 · 第一阶段(基础与全局)

实验日期:2026-09-30

实验环境:Raspberry Pi(192.168.0.108,wlan0)+ Mac(192.168.0.106)+ Wireshark 4.4.8


一、当天目标与产出

项目 内容
目标 看到"连不上 / 卡顿 / 延迟"时,脑子里能浮现一条"包的旅程":从哪出发 → 经过哪些节点 → 在哪丢了或慢了
路线图实验 抓包观察一次 HTTP / TCP / UDP 通信
实际完成 实验 A(DNS)、B(HTTP/TCP)、C(UDP)、D(延迟与路径排查)
产出文件 dns.pcap、http.pcap、udp.pcap、Follow TCP Stream 截图

二、核心概念

1. 封装:一个包是层层"套信封"

复制代码
应用数据(HTTP 请求 / RTSP 指令 / RTP 视频载荷)
 └ 加 TCP/UDP 头(源端口、目的端口...)        → 段 / 数据报
   └ 加 IP 头(源 IP、目的 IP、TTL)         → 包
     └ 加以太网头(源 MAC、目的 MAC)        → 帧

一句话:IP 决定"去哪台机器",端口决定"找哪个程序"。

2. TCP 与 UDP

TCP UDP
连接 三次握手建立,四次挥手关闭 无连接,直接发
可靠性 丢了重传,保证顺序 丢了就丢了,发送方不知道
头部大小 20 字节起(本次抓包含时间戳选项为 32 字节) 固定 8 字节、4 个字段
摄像头里的用途 HTTP API、RTSP 控制信令、鉴权 RTP 视频 / 音频流

对应关系:控制面要可靠 → TCP;媒体面要实时 → UDP(迟到的旧帧没有价值,重传只会增加延迟)。

3. 局域网、NAT 与公网

  • 私网地址段:10.x、172.16--31.x、192.168.x,只在内部有效。
  • NAT 把"私网 IP:端口"翻译成"公网 IP:端口"再发出。外部默认连不到内部设备。
  • 所以摄像头产品几乎都走云中转或 P2P 打洞,而不是让用户自己做端口映射。

4. 防火墙要想到四层

  1. NAT(地址转换)
  2. 路由器防火墙
  3. 云服务商安全组(最容易忘)
  4. 设备本机防火墙

5. TTL 与逐跳转发

IP 头里的 TTL 每经过一台路由器减 1,减到 0 时该路由器丢弃包并回一个 ICMP 超时消息。traceroute 就是利用这一点,把每一跳的路由器找出来。

6. 路由选"最具体的"

路由表按最长前缀匹配 选路。VPN 软件常加 0.0.0.0/1 和 128.0.0.0/1 两条路由来覆盖全部公网流量,而 192.168.0.0/24 因前缀更长,局域网流量仍然直连。


三、实验记录

实验 A:DNS(UDP 53)

bash 复制代码
sudo tcpdump -i wlan0 -n udp port 53 -w dns.pcap
dig example.com
  • 抓到 2 个包:1 个查询、1 个应答。
  • DNS 服务器 223.5.5.5,协议 UDP,耗时 36ms,返回两条 A 记录。

实验 B:HTTP over TCP

bash 复制代码
# Pi
sudo tcpdump -i wlan0 -n tcp port 8080 -w http.pcap
# Mac
curl -v http://192.168.0.108:8080/

共抓到 14 个包 ,去掉 3 个重复包为 11 个有效包,整个过程约 19ms。

No. 方向 标志 含义
1 Mac → Pi SYN 握手第 1 步
2 Pi → Mac SYN, ACK 握手第 2 步
3、4 (重复) 见"问题 3"
5 Mac → Pi ACK 握手第 3 步,连接建立
6 (重复) 重复的 ACK
7 Mac → Pi PSH, ACK,81 字节 GET / HTTP/1.1
8 Pi → Mac ACK 确认收到请求(Ack=82)
9 Pi → Mac PSH, ACK,112 字节 响应头
10 Pi → Mac FIN, PSH, ACK,15 字节 响应体 camera-demo ok,并带 FIN,服务端先关闭
11 Mac → Pi ACK 确认响应头(Ack=113)
12 Mac → Pi ACK 确认响应体和 FIN(Ack=129)
13 Mac → Pi FIN, ACK 客户端关闭
14 Pi → Mac ACK 最后确认,连接关闭

包数分类:握手 3 + 重复 3 + 带数据 3(7、9、10)+ 纯确认 2(8、11)+ 挥手 3(12、13、14)= 14。

字节数核对

  • 请求 81 字节:GET / HTTP/1.1\r\n(16)+ Host: ...(26)+ User-Agent: curl/8.7.1(24)+ Accept: */*(13)+ 空行(2)。
  • 响应头 112 字节:状态行 17 + Server 行 36 + Date 行 37 + Content-Length 行 20 + 空行 2。
  • 响应体 15 字节 = camera-demo ok + 换行,与 Content-Length: 15 一致。
  • 整个对话 81 + 112 + 15 = 208 字节,与 Follow TCP Stream 窗口显示一致。

HTTP/1.0 的特征 :第 10 包是服务端主动带 FIN,说明 Python BaseHTTP 是"一个请求一条连接,发完就关";HTTP/1.1 长连接不会这样。

实验 C:UDP

bash 复制代码
# Pi 终端 1
sudo tcpdump -i wlan0 -n udp port 9999 -X -w udp.pcap
# Pi 终端 2
nc -u -l 9999
# Mac
echo "hello camera" | nc -u 192.168.0.108 9999

抓到 1 个包 :192.168.0.106.63658 > 192.168.0.108.9999: UDP, length 13。

复制代码
IP 头(20 字节)   45 00 0029 ... 40(TTL=64) 11(协议=UDP) ... c0a8006a(源) c0a8006c(目的)
UDP 头(8 字节)   f8aa(源端口 63658)  270f(目的端口 9999)  0015(长度 21)  ccc8(校验和)
数据(13 字节)    68 65 6c 6c 6f 20 63 61 6d 65 72 61 0a  = "hello camera\n"
  • 数据区之后多出的一个 00 不属于 UDP 数据(UDP 长度字段只有 13 字节数据),推测是以太网最小帧长的填充。
  • 客户端端口随机(63658)、服务端端口固定(9999),与 TCP 一致。
  • nc -u 发完不会自己退出:UDP 没有连接关闭的概念。

实验 D:延迟与路径排查

bash 复制代码
ping -c 10 154.8.173.130
ss -tn
traceroute -n 223.5.5.5
sudo traceroute -I -n 223.5.5.5

D-1 云服务器不可达(分层排查)

检查项 结果 结论
ping 192.168.0.1 0% 丢包,约 2ms Pi 到路由器正常
ping 223.5.5.5 0% 丢包,约 40ms 公网出口正常
ping 154.8.173.130 100% 丢包 只有这台服务器不可达
ss -tnp 到 154.8.173.130:1883 一直 SYN-SENT,进程为 Python(pid 4502) 握手第 1 步后无回应
最终确认 腾讯云服务器到期未续费 根因

超时与拒绝的区别

现象 含义
Connection refused(收到 RST) 服务器在线,但端口没有程序监听
一直 SYN-SENT / 超时 服务器无回应:关机、不存在,或被防火墙静默丢弃

D-2 ss -tn 的其他观察

  • 1883 是 MQTT 默认端口,1935 是 RTMP 默认端口,Pi 上有程序在尝试连云服务器这两个服务。
  • 本机 8554(常见 RTSP 备用端口)有一条连接 Send-Q 约 2.2MB、对端 Recv-Q 约 112KB,说明客户端读得比服务端送得慢,数据在堆积(背压)。这是 Day 09--11 视频卡顿的典型成因之一。

D-3 traceroute 对照(223.5.5.5,Pi,ICMP 模式,共 16 跳)

跳 地址 耗时 含义
1 192.168.0.1 ≈3ms 第一层路由器(默认网关)
2 192.168.1.1 ≈3ms 第二层网关(私网)
3 10.12.128.1 ≈8ms 运营商内部接入设备(私网)
4--5 120.80.x / 120.82.x 7--10ms 运营商本地网络
6 219.158.7.225 ≈47ms 延迟跳升,进入跨城骨干链路
7--9 125.33.x / 61.148.x / 61.49.x ≈39ms 骨干 / 目标区域网络
10--15 * * * 无 设备转发了包但不回应探测
16 223.5.5.5 ≈42--46ms 终点
  • 家里有两层私网网关 (192.168.0.1 → 192.168.1.1)加运营商的 10.x,说明包出门前经过多次地址转换。
  • 跳数多不等于慢;慢主要来自"跨了多远"(第 5→6 跳多出约 37ms)。
  • ping 的 ttl=49 与 16 跳的路径量级吻合(假设对端初始 TTL 为 64,则回程经过约 15 台路由器)。

D-4 UDP 与 ICMP 两种探测方式

方式 命令 结果
UDP(默认) traceroute -n 223.5.5.5 第 9 跳后全是 *,没走到终点
ICMP sudo traceroute -I -n 223.5.5.5 第 16 跳到达 223.5.5.5

同一台 Pi、同一个(可达的)目标,换一种探测方式结果就不同。* * * 只表示该跳没有回应探测包,不等于包被丢了。

D-5 Mac 开关 VPN 的对照

VPN 开(utun4) VPN 关(直连)
route -n get 223.5.5.5 128.0.0.0/1,网关 10.8.0.1,接口 utun4 ---
traceroute 第 1 跳 10.8.0.1,≈50ms 192.168.0.1,≈3ms
路径 进入隧道对端内部网络 家里路由 → 二级网关 → 运营商

四、问题与解决汇总

# 现象 原因 解决 / 结论
1 http.pcap 为 0 字节,0 packets captured 在 Pi 上 curl Pi 自己的 IP,流量走回环接口 lo,不经过 wlan0;且过滤条件写了 host 154.8.173.130,与该次通信两端无关 改为 Mac curl Pi,Pi 上抓 wlan0 的 tcp port 8080。知识点:同一台机器内部通信不出网卡
2 http.pcap 中第 3、4、6 包为红色(Out-Of-Order / Dup ACK) 第 4 包是第 2 包的完整复制(Pi 收到重复 SYN 后重发 SYN-ACK);第 3 包是 Mac 的第二个 SYN(缺 ECE/CWR 标志);第 6 包是第 5 包的重复 能确定它们是什么,但不能确定根本原因(Wi-Fi 链路延迟 / macOS 的 ECN 回退 / 多接口,均未验证)。不影响通信结果。红色异常 ≠ 故障
3 UDP 首次抓到的不是 hello camera 先启动了 nc -l 收到数据后才启动 tcpdump;抓到的是 Pi 端 nc 里按回车产生的 1 字节(0a)回包 先抓包后发送,且不在 nc 终端按回车。重抓得到 13 字节数据包
4 ping 腾讯云 100% 丢包,ss 显示 SYN-SENT 云服务器到期未续费 见实验 D-1
5 Mac 的 traceroute 第 1 跳 ≈50ms、走 10.8.0.1 Mac 开了 VPN,公网流量经 utun4 隧道 测公网延迟前先确认 VPN 状态
6 同一目标 traceroute 末尾全是 * * *,看似不可达 默认 UDP 探测不一定被回应 用 -I 走 ICMP 对照;* * * 不能单独作为不可达的证据
7 《包的旅程》第 1 题包数分类有误 "1 个数据"实为 3 个带数据包 + 2 个纯 ACK;"4 个挥手"实为 3 个(首个 FIN 搭在第 10 包) 按第三节"包数分类"修正

五、关键认知

  1. 同机通信走 lo,不出网卡。抓包前先想清楚流量会经过哪个接口。
  2. 抓包三步法:先看方向(谁发给谁)→ 再看标志(SYN / ACK / FIN)→ 最后看序号(数据是否连续)。
  3. Ack 是"我期望收到的下一个字节编号";FIN 也占 1 个序号。
  4. 红色异常包 ≠ 故障,要看是否持续出现、是否影响最终结果。
  5. 超时 ≠ 拒绝:超时查网络和服务器本身,拒绝查服务进程。
  6. 没有对照组的观察容易被当成结论 。traceroute、ping、ss 要互相印证。
  7. 排查要在出问题的那台设备上做,且要先确认 VPN 等变量。
  8. 路径由路由表的最长前缀匹配决定,VPN 与局域网可同时存在而互不干扰。
  9. 客户端端口随机、服务端端口固定,TCP 和 UDP 都一样。
  10. UDP 发送方不知道对方是否收到;TCP 靠 ACK 确认并重传。

六、命令速查

bash 复制代码
# 抓包(Pi)
sudo tcpdump -i wlan0 -n tcp port 8080 -w http.pcap      # 抓并存文件
tcpdump -n -r http.pcap                                   # 回放摘要
tcpdump -n -X -r udp.pcap                                 # 回放并显示十六进制

# 拷贝到 Mac
scp h***x@192.168.0.108:~/http.pcap ~/Desktop/

# 连通性与路径
ping -c 3 192.168.0.1                 # 网关
ping -c 3 223.5.5.5                   # 公网 IP(不依赖 DNS)
sudo traceroute -I -n 223.5.5.5       # ICMP 方式,判断是否到达
ip route                              # 路由表(Linux)
route -n get 223.5.5.5                # 路由(macOS),看 interface 是否为 utun

# 连接状态
ss -tn                                # TCP 连接
sudo ss -tnp | grep -E '1883|1935'    # 带进程

# UDP 手动通信
nc -u -l 9999                         # 接收
echo "hello camera" | nc -u <ip> 9999 # 发送

Wireshark 显示过滤器

复制代码
tcp.port == 8080            ip.addr == 192.168.0.108
udp.port == 9999            dns
tcp.flags.syn == 1          tcp.analysis.flags
tcp.analysis.retransmission

七、下一步

Day 04 · HTTP / API:控制链入口 ------ 理解 REST、状态码、鉴权、超时、重试、幂等;实验:写一个最小设备管理 API,把"接口异常"变成可定位的问题。

相关推荐
ayaya_mana1 小时前
MCTier 组网联机工具:安装、配置与私有化部署
网络·windows·内网穿透·联机
故七月1 小时前
GEO 信源评估体系:如何判断一条网页信源能否被大模型采信
前端·网络·人工智能
dadaobusi1 小时前
学习:AXI协议
学习
xxwl5851 小时前
vue3的入门学习
前端·vue.js·学习
Joe_Wang51 小时前
【从0到1学习JVM · 21】既不浪费空间又没有碎片,标记整理算法到底慢在哪
jvm·学习·算法·垃圾回收·标记整理算法
hasty1 小时前
一次 WebSocket 握手为何能终止进程?Undici CVE-2026-19534 的异常边界
网络·websocket·网络协议
个 人 练 习 生2 小时前
C++:模板初阶详解
开发语言·c++·经验分享·学习
辣知2 小时前
辣知·化智69 西周青铜器何尊的宅兹中国
学习
AOI小白新手上路2 小时前
韦东山 3-5 I.MX6ULL 的 LED 编程 · 学习笔记
arm开发·笔记·单片机·学习·架构·硬件架构