网络知识实用指南
Table of Contents
网络知识实用指南 #
目录 #
1. 网络分层模型(OSI/TCP-IP) #
1.1 为什么需要分层? #
想象一下寄快递:
- 应用层:你写的内容(“生日快乐”)
- 传输层:快递单(TCP/UDP,保证送到)
- 网络层:地址(IP,知道往哪送)
- 数据链路层:运输方式(Wi-Fi/网线,物理传输)
- 物理层:电信号(0和1)
每一层只关心自己的事,下层为上层服务。
1.2 TCP/IP 四层模型(实际使用) #
┌─────────────────────────────────────┐
│ 应用层 (Application Layer) │ ← HTTP, MQTT, SSH, FTP
│ 你写的代码在这里 │
├─────────────────────────────────────┤
│ 传输层 (Transport Layer) │ ← TCP, UDP
│ 保证数据可靠传输 │
├─────────────────────────────────────┤
│ 网络层 (Internet Layer) │ ← IP, ICMP
│ 路由和寻址 │
├─────────────────────────────────────┤
│ 链路层 (Link Layer) │ ← Ethernet, Wi-Fi
│ 物理传输 │
└─────────────────────────────────────┘
关键理解:
- 上层协议必须依赖下层协议
- HTTP 跑在 TCP 上,TCP 跑在 IP 上,IP 跑在网线上
- 所有网络协议最终都要通过 Socket(操作系统接口)发送
2. IP地址与端口 #
2.1 IP地址是什么? #
IP地址 = 网络世界的门牌号
- IPv4:32位,4个数字,如
192.168.1.100 - IPv6:128位,如
2001:0db8:85a3:0000:0000:8a2e:0370:7334(目前主要用IPv4)
2.2 内网IP vs 公网IP #
┌─────────────────────────────────────────────┐
│ 互联网(公网) │
│ 公网IP: 120.77.250.123 │
│ (全球唯一,可从任何地方访问) │
└───────────────────┬─────────────────────────┘
│
┌─────▼─────┐
│ 路由器 │ (NAT设备)
│ WAN: 120.77.250.123 (公网IP)
│ LAN: 192.168.1.1 (内网网关)
└─────┬─────┘
│
┌───────────────┼───────────────┐
│ │ │
┌───▼───┐ ┌─────▼────┐ ┌─────▼────┐
│ 手机 │ │ 电脑 │ │ 机器人 │
│192.168│ │192.168. │ │192.168. │
│ 1.101 │ │ 1.102 │ │ 1.100 │
└───────┘ └──────────┘ └──────────┘
内网IP(局域网内可访问,外网无法直接访问)
常见内网IP段:
192.168.x.x(家用路由器最常见)10.x.x.x(企业内网)172.16.x.x ~ 172.31.x.x(企业内网)
为什么需要内网IP?
- IPv4地址不够用(全球只有43亿个)
- 一个公网IP可以带N个内网设备(通过NAT)
2.3 端口(Port) #
端口 = 门牌号里的房间号
- IP地址找到"哪栋楼"(设备)
- 端口找到"哪个房间"(应用)
常见端口:
80:HTTP443:HTTPS22:SSH1883:MQTT3306:MySQL6379:Redis
端口范围:
0-1023:系统保留端口(需要root权限)1024-65535:用户可用端口
完整地址格式:IP:端口
- 例如:
192.168.1.100:7999
3. TCP vs UDP #
3.1 TCP(传输控制协议) #
特点:可靠、有序、面向连接
比喻:打电话
- 先拨号(三次握手建立连接)
- 对方必须接听才能说话
- 保证每句话都听到(重传机制)
- 挂断前说"再见"(四次挥手)
适用场景:
- HTTP网页浏览
- 文件传输(FTP)
- 邮件(SMTP)
- 数据库连接
缺点:
- 速度慢(要确认、要重传)
- 开销大(头部长)
3.2 UDP(用户数据报协议) #
特点:快速、无连接、不可靠
比喻:发短信
- 不需要对方接听,直接发
- 不保证对方收到
- 不保证顺序
- 发完就走
适用场景:
- 视频直播(丢几帧无所谓)
- 游戏(延迟低更重要)
- DNS查询(快就行)
- HTTP/3.0 (QUIC)
缺点:
- 可能丢包
- 可能乱序
3.3 对比表 #
| 特性 | TCP | UDP |
|---|---|---|
| 连接 | 需要建立连接(握手) | 无连接 |
| 可靠性 | 保证送达 | 不保证 |
| 顺序 | 保证顺序 | 不保证 |
| 速度 | 较慢 | 很快 |
| 开销 | 大(20字节头) | 小(8字节头) |
| 适用 | 重要数据 | 实时数据 |
4. Socket(套接字) #
4.1 Socket是什么? #
Socket = 操作系统提供的"网线插口"
所有网络通信的最底层接口。
4.2 Socket的工作方式 #
应用程序
↓
Socket API (send/recv)
↓
操作系统内核
↓
网卡驱动
↓
物理网线/Wi-Fi
关键理解:
- HTTP、MQTT、ZMQ 等所有协议,最终都要调用 Socket
- Socket 是操作系统提供的,不是某个编程语言特有的
- Python 的
socket库、C 的socket()函数,底层都是同一个东西
4.3 Socket的类型 #
- TCP Socket:可靠连接(HTTP用这个)
- UDP Socket:快速无连接(DNS用这个)
- Unix Socket:本地进程通信(不经过网络)
5. HTTP协议家族 #
5.1 HTTP/1.0 #
特点:一次请求一次连接
客户端 → [建立连接] → 服务器
客户端 → [发送请求] → 服务器
客户端 ← [返回响应] ← 服务器
客户端 → [断开连接] → 服务器
问题:每个请求都要握手,慢!
5.2 HTTP/1.1 #
改进:Keep-Alive(连接复用)
客户端 → [建立连接] → 服务器
客户端 → [请求1] → 服务器
客户端 ← [响应1] ← 服务器
客户端 → [请求2] → 服务器 ← 复用连接!
客户端 ← [响应2] ← 服务器
客户端 → [断开连接] → 服务器
特点:
- 一个连接可以发多个请求
- 但必须串行(请求1完了才能发请求2)
- 服务器不能主动推送(必须客户端先问)
5.3 HTTP/2.0 #
改进:多路复用(Multiplexing)
客户端 → [建立连接] → 服务器
客户端 → [请求1] ─┐
客户端 → [请求2] ─┤
客户端 → [请求3] ─┼→ 服务器 ← 同时发多个!
客户端 ← [响应1] ─┤
客户端 ← [响应2] ─┤
客户端 ← [响应3] ─┘
特点:
- 并行发送多个请求(不用等)
- 头部压缩(HPACK)
- 服务器推送(Server Push,但使用受限)
问题:底层还是TCP,TCP有"队头阻塞"(一个包丢了,后面的都要等)
5.4 HTTP/3.0 (QUIC) #
革命性改进:基于UDP
HTTP/3.0 = UDP + 自己实现的可靠性机制
特点:
- 0-RTT连接:第二次访问网站,连握手都省了
- 多路复用无队头阻塞:每个流独立,一个流丢包不影响其他流
- 内置加密:TLS 1.3 内置在协议里
为什么用UDP?
- TCP是操作系统实现的,改不动
- UDP是"白纸",可以在应用层自己实现更好的可靠性
5.5 HTTP协议对比 #
| 版本 | 底层协议 | 连接方式 | 全双工 | 服务器推送 |
|---|---|---|---|---|
| HTTP/1.0 | TCP | 一次一连接 | ❌ | ❌ |
| HTTP/1.1 | TCP | Keep-Alive复用 | ❌ | ❌ |
| HTTP/2.0 | TCP | 多路复用 | ⚠️(有限) | ⚠️(受限) |
| HTTP/3.0 | UDP | 多路复用+0-RTT | ⚠️(有限) | ⚠️(受限) |
6. MQTT协议 #
6.1 MQTT是什么? #
MQTT = 物联网专用协议
设计目标:带宽敏感、低功耗、简单
6.2 MQTT的核心特点 #
1. 发布/订阅模式(Pub/Sub) #
┌─────────┐ ┌─────────┐
│ 机器人1 │──发布消息───────────→│ │
└─────────┘ │ MQTT │
│ Broker │
┌─────────┐ │ (服务器) │
│ 手机App │←──订阅消息───────────│ │
└─────────┘ └─────────┘
- 发布者(Publisher):发消息,不关心谁收
- 订阅者(Subscriber):订阅Topic,自动收消息
- Broker(服务器):负责转发
2. 全双工通信 #
- 客户端 → 服务器:随时可以Publish消息
- 服务器 → 客户端:随时可以推送消息到订阅的Topic
- 可以同时双向,不需要"你先说,我再说"
3. 长连接 + Keep-Alive #
客户端 → [建立TCP连接] → Broker
客户端 → [保持连接,永不挂断]
客户端 → [每60秒发心跳包] → Broker
客户端 ← [随时推送消息] ← Broker
4. 极小的协议头 #
- 最小只有2字节(HTTP头至少几百字节)
- 适合2G/NB-IoT这种极低带宽场景
6.3 MQTT vs HTTP #
| 特性 | HTTP | MQTT |
|---|---|---|
| 底层 | TCP | TCP |
| 连接 | 短连接(Keep-Alive可复用) | 长连接(必须保持) |
| 模式 | 请求-响应 | 发布-订阅 |
| 全双工 | ❌ | ✅ |
| 服务器推送 | ❌(HTTP/2有限) | ✅(原生支持) |
| 协议头 | 大(几百字节) | 小(最小2字节) |
| 适用 | Web浏览 | IoT、实时消息 |
6.4 为什么IoT用MQTT? #
- 带宽敏感:机器人可能在信号差的角落,每个字节都珍贵
- 低功耗:长连接比频繁握手省电
- 服务器主动推送:云端可以随时下发指令,不需要机器人轮询
- QoS保证:协议层自带"保证送达"机制
7. NAT与路由器 #
7.1 什么是NAT? #
NAT (Network Address Translation) = 网络地址转换
比喻:公司前台
- 外线电话打进来,前台转接给内部分机
- 内部分机打出去,显示的是公司总机号码
7.2 NAT的工作流程 #
场景1:内网主动访问外网(出站,简单) #
步骤1: 机器人访问百度
┌─────────┐
│ 机器人 │ 源IP: 192.168.1.100:5000
│ │ 目标: 220.181.38.148:80
└────┬────┘
│
▼
┌─────────┐
│ 路由器 │ NAT转换:
│ (NAT) │ 192.168.1.100:5000 → 120.77.250.123:10001
└────┬────┘
│
▼
互联网 → 百度收到请求,源IP是 120.77.250.123:10001
步骤2: 百度返回数据
百度 → 120.77.250.123:10001
│
▼
┌─────────┐
│ 路由器 │ 查NAT表:
│ (NAT) │ 120.77.250.123:10001 → 192.168.1.100:5000
└────┬────┘
│
▼
┌─────────┐
│ 机器人 │ 收到响应
└─────────┘
关键:路由器记住了这个映射(NAT表),所以回来的数据知道给谁。
场景2:外网主动访问内网(入站,困难) #
问题:外网不知道内网设备的IP,无法直接访问!
解决方案:
- 端口映射(Port Forwarding):手动配置路由器
- UPnP:自动配置(不安全)
- SSH隧道:通过中间服务器转发(见SSH章节)
7.3 路由器的作用 #
路由器 = NAT设备 + 交换机 + DHCP服务器
- NAT功能:内网IP ↔ 公网IP转换
- 路由功能:决定数据包往哪走
- DHCP功能:自动给内网设备分配IP
- 防火墙功能:过滤危险数据包
8. SSH与远程连接 #
8.1 SSH是什么? #
SSH (Secure Shell) = 安全的远程登录协议
用途:
- 远程登录服务器
- 执行命令
- 传输文件(SFTP)
- 端口转发(隧道)
8.2 SSH的基本使用 #
# 登录远程服务器
ssh user@192.168.1.100
# 指定端口
ssh -p 2222 user@192.168.1.100
# 使用密钥(免密登录)
ssh -i ~/.ssh/id_rsa user@192.168.1.100
8.3 SSH隧道(端口转发) #
SSH隧道 = 通过SSH连接,把本地端口映射到远程端口
本地端口转发(Local Port Forwarding) #
场景:访问内网服务器的服务
# 把本地7999端口映射到内网服务器的7999端口
ssh -L 7999:192.168.1.100:7999 user@jump_server.com
流程:
本地应用 → localhost:7999 → SSH隧道 → jump_server → 192.168.1.100:7999
远程端口转发(Remote Port Forwarding) #
场景:让外网访问内网服务
# 把远程服务器的8080端口映射到本地的80端口
ssh -R 8080:localhost:80 user@remote_server.com
流程:
外网 → remote_server:8080 → SSH隧道 → 本地:80
8.4 为什么SSH隧道能"绕过"NAT? #
关键:SSH连接是内网主动发起的(出站),NAT允许!
内网设备 → [主动建立SSH连接] → 跳板服务器
(NAT允许,因为是出站)
跳板服务器 ← [数据通过已建立的SSH连接] ← 内网设备
(数据走的是已建立的连接,NAT认识)
9. DNS域名解析 #
9.1 DNS是什么? #
DNS (Domain Name System) = 域名系统
作用:把人类能记住的域名(如 www.baidu.com)转换成IP地址(如 220.181.38.148)
9.2 DNS查询流程 #
1. 浏览器输入 www.baidu.com
↓
2. 查询本地DNS缓存(有没有?)
↓ 没有
3. 查询本地DNS服务器(路由器/ISP)
↓ 没有
4. 查询根DNS服务器(.)
↓
5. 查询.com DNS服务器
↓
6. 查询 baidu.com DNS服务器
↓
7. 返回IP: 220.181.38.148
↓
8. 浏览器访问这个IP
9.3 常用DNS服务器 #
- 8.8.8.8:Google DNS
- 1.1.1.1:Cloudflare DNS
- 114.114.114.114:国内DNS
10. 网络诊断与排错 #
10.1 常用命令 #
ping - 测试连通性 #
# 测试能否到达目标
ping www.baidu.com
# 指定次数
ping -c 4 192.168.1.1
# 指定间隔(秒)
ping -i 2 192.168.1.1
输出解读:
time=10ms:延迟10毫秒(越小越好)100% packet loss:完全不通Request timeout:超时(可能防火墙拦截)
traceroute - 追踪路由 #
# 查看数据包经过的路由
traceroute www.baidu.com
# Windows用
tracert www.baidu.com
用途:找出网络在哪个节点卡住了。
netstat - 查看网络连接 #
# 查看所有连接
netstat -an
# 查看监听端口
netstat -ln
# 查看TCP连接
netstat -ant
# 查看进程
netstat -anp | grep 7999
ss - 现代版netstat(Linux) #
# 查看所有连接
ss -an
# 查看监听端口
ss -ln
# 查看特定端口
ss -an | grep 7999
curl - HTTP测试 #
# 测试HTTP请求
curl http://www.baidu.com
# 显示详细信息
curl -v http://www.baidu.com
# 测试HTTPS
curl https://www.baidu.com
# 指定超时
curl --connect-timeout 5 http://www.baidu.com
telnet - 测试端口是否开放 #
# 测试端口连通性
telnet 192.168.1.100 7999
# 如果显示"Connected",说明端口开放
# 如果显示"Connection refused",说明端口关闭或服务未启动
nslookup / dig - DNS查询 #
# 查询域名IP
nslookup www.baidu.com
# 使用dig(更详细)
dig www.baidu.com
# 指定DNS服务器
dig @8.8.8.8 www.baidu.com
10.2 常见网络错误 #
Connection refused(连接被拒绝) #
原因:
- 目标端口没有服务在监听
- 防火墙拦截
- 服务未启动
排查:
# 1. 检查服务是否启动
ps aux | grep your_service
# 2. 检查端口是否监听
netstat -ln | grep 7999
# 3. 检查防火墙
sudo iptables -L
Connection timeout(连接超时) #
原因:
- 网络不通(路由问题)
- 防火墙丢弃(不回复)
- 目标不存在
排查:
# 1. ping测试
ping target_ip
# 2. traceroute追踪
traceroute target_ip
# 3. 检查防火墙规则
Name resolution failed(DNS解析失败) #
原因:
- DNS服务器不可达
- 域名不存在
- 本地DNS缓存错误
排查:
# 1. 测试DNS服务器
nslookup www.baidu.com 8.8.8.8
# 2. 清除DNS缓存(Linux)
sudo systemd-resolve --flush-caches
# 3. 检查/etc/resolv.conf
cat /etc/resolv.conf
Network unreachable(网络不可达) #
原因:
- 路由表没有到目标的路由
- 网关配置错误
排查:
# 1. 查看路由表
route -n
# 或
ip route
# 2. 检查网关
ip route | grep default
10.3 网络性能诊断 #
带宽测试 #
# 使用iperf3测试带宽
# 服务器端
iperf3 -s
# 客户端
iperf3 -c server_ip
延迟测试 #
# ping测试延迟
ping -c 100 www.baidu.com | tail -1
# 输出:rtt min/avg/max/mdev = 10.123/15.456/20.789/2.345 ms
丢包率测试 #
# ping测试丢包
ping -c 100 www.baidu.com
# 查看最后的统计:100 packets transmitted, 95 received, 5% packet loss
10.4 实际项目中的网络诊断 #
检查MQTT连接 #
# 在你的代码中,MQTT超时通常意味着:
# 1. 网络延迟高
# 2. 带宽不足
# 3. 防火墙拦截
# 参考:src/duck/control_stage/common/robot_base_status.py
# 当MQTT超时时,会等待30秒后重试
检查HTTP连接 #
# 使用curl或requests测试
import requests
try:
response = requests.get('http://target', timeout=5)
print(f"状态码: {response.status_code}")
except requests.exceptions.Timeout:
print("连接超时")
except requests.exceptions.ConnectionError:
print("连接错误")
检查SSH连接 #
# 测试SSH连接
ssh -v user@target_ip
# -v 显示详细信息,可以看到连接过程
11. 实用总结 #
11.1 协议选择指南 #
| 场景 | 推荐协议 | 原因 |
|---|---|---|
| Web浏览 | HTTP/2.0 或 HTTP/3.0 | 性能好 |
| IoT设备 | MQTT | 带宽敏感、服务器推送 |
| 文件传输 | FTP/SFTP | 大文件 |
| 实时视频 | UDP | 延迟低 |
| 数据库 | TCP(MySQL/PostgreSQL) | 可靠性重要 |
| 远程登录 | SSH | 安全 |
11.2 网络问题排查流程 #
1. 问题现象是什么?
↓
2. ping测试(网络是否通?)
↓ 不通
3. traceroute(在哪断了?)
↓
4. 检查DNS(域名解析对吗?)
↓
5. 检查端口(服务在监听吗?)
↓
6. 检查防火墙(被拦截了吗?)
↓
7. 检查服务日志(服务本身有问题吗?)
11.3 关键概念速查 #
- IP地址:设备的门牌号
- 端口:应用的房间号
- TCP:可靠传输(打电话)
- UDP:快速传输(发短信)
- Socket:操作系统提供的网线插口
- HTTP:Web协议(请求-响应)
- MQTT:IoT协议(发布-订阅,全双工)
- NAT:内网IP转公网IP
- SSH:安全远程登录 + 隧道
- DNS:域名转IP地址
附录:常用端口速查 #
| 端口 | 协议/服务 | 说明 |
|---|---|---|
| 22 | SSH | 远程登录 |
| 80 | HTTP | Web服务 |
| 443 | HTTPS | 安全Web服务 |
| 1883 | MQTT | MQTT协议 |
| 3306 | MySQL | 数据库 |
| 6379 | Redis | 缓存 |
| 8080 | HTTP | 常用Web备用端口 |
| 7999 | 自定义 | 你的项目常用端口 |
文档版本:v1.0
最后更新:2025-01-XX