传统客户端-服务器架构的工作方式
核心流程如下:
消息路径:你发送的消息不会直接发到好友的 IP 地址,而是先发送到微信的服务器(腾讯的中央服务器集群)。
IP 与账号的映射:当你登录微信时,客户端会与微信服务器建立长连接(例如基于 TCP 或 HTTP/2、WebSocket 等),此时微信服务器会记录你的账号 ID 和当前连接所对应的 IP 地址与端口。好友上线时同样如此。
消息中转:当你发消息给好友时,消息先被加密并发送到微信服务器,服务器根据好友的账号 ID 查找其当前连接的 IP 和端口,再将消息转发给对方。
没有直接 IP 暴露:在整个过程中,你和好友都不知道对方的真实 IP 地址,所有通信都经过微信服务器中转(或通过服务器协调后建立点对点连接,但在微信这类应用中,通常以中转为主)。
补充说明:
微信服务器并不需要“写死”一个固定的 IP 地址给你连接,而是通过域名(如
weixin.qq.com)由 DNS 解析到多个服务器地址,客户端通常会选择最优的服务器接入。微信的服务器集群会维护一个在线用户会话表,实时更新每个账号所连接的网关服务器地址和网络信息,以便正确路由消息。
如果好友不在线,消息会暂存在服务器上,待其上线后再推送。
因此,你的结论是正确的:
微信服务器作为中间桥梁,维护了在线用户的账号与网络地址的映射关系,消息通过服务器中转,双方的真实 IP 不会直接暴露给对方。
举个生活中的例子 🌟
场景:内网里的两个微信用户想直接视频通话
想象一下:
你(在家庭WiFi里,IP:
192.168.1.100)朋友(在公司网络里,IP:
10.0.0.50)
问题来了:
你俩的IP都是内网地址(局域网IP)
彼此直接看不见对方
所有数据都要通过微信服务器转发
这样做的缺点:
视频延迟高(数据要绕到服务器)
服务器压力大(要转发所有视频流)
速度慢
STUN是干什么的?🚀
STUN是干什么的?🚀
STUN就像是一个"地址查询服务":
第一步:问路
text
你的手机(在NAT后) STUN服务器(公网上) | | |---- "我在哪里?" ---------------->| | | |<---- "你的公网地址是: | | 203.0.113.25:54321" ---------|
STUN服务器告诉你:
"从外面看,你的地址是
203.0.113.25:54321,不是192.168.1.100"
第二步:交换地址
你 微信服务器 朋友 |---- "我的公网地址是..." ---> | | | |---- "他的公网地址是..." ------>|
第三步:直接连接
你(203.0.113.25:54321) <======== 直接P2P连接 ========> 朋友(198.51.100.10:12345) (不再经过微信服务器!)
为什么需要这么麻烦?🤔
因为NAT设备(路由器)的行为很复杂:因为你和微信服务器通信使用的公网映射端口与 你直接和朋友通信的公网映射端口 是不一样的,NAT的端口分发是源相关的也是目标相关的。具体实例看【路由器-AP、DHCP、ARP、广播帧、交换机、信道】-初级知识串联(二)。
实际例子:微信视频通话 📱
没有STUN的情况
你 → 路由器 → 微信服务器 → 朋友的路由器 → 朋友 ↑ ↑ NAT NAT
问题:所有视频数据都要经过微信服务器,延迟高,服务器贵
有STUN的情况
# 1. 先查地址 你 → STUN服务器:"我在哪?" STUN → 你:"你是203.0.113.25:54321" 朋友 → STUN服务器:"我在哪?" STUN → 朋友:"你是198.51.100.10:12345" # 2. 通过微信交换地址 你告诉微信:"我的公网地址是203.0.113.25:54321" 朋友告诉微信:"我的公网地址是198.51.100.10:12345" 微信把地址交换给你们俩 # 3. 直接连接 你(203.0.113.25:54321) ↔ 朋友(198.51.100.10:12345)
stun服务器在微信通过中的拓扑图是什么样的?是如何起作用的
核心澄清:STUN的“盲眼”工作方式
STUN服务器是一个“瞎子”,它:
不知道你要和谁通话
不认识你的微信账号
不关心你的通信内容
它只做一件事:“谁问我,我就告诉谁它的公网地址是什么”。
图解STUN的“盲眼”工作原理
场景:你在家里(内网),通过NAT路由器上网 ┌─────────────┐ ┌──────────┐ ┌─────────────┐ │ 你的设备 │ │ NAT路由器 │ │ STUN服务器 │ │192.168.1.100│ │ │ │ 1.2.3.4:3478│ └──────┬──────┘ └────┬─────┘ └──────┬──────┘ │ │ │ │ 1.发送UDP包 │ │ │ 源:192.168.1.100:12345│ │ │ 目:1.2.3.4:3478 │ │ ├─────────────────►│ │ │ │ │ │ │ 2.NAT创建映射 │ │ │ 内网:192.168.1.100:12345│ │ │ → 公网:203.0.113.25:54321│ │ │ │ │ │ 3.转发包 │ │ │ 源:203.0.113.25:54321│ │ │ 目:1.2.3.4:3478 │ │ ├───────────────────►│ │ │ │ │ │ │ │ │ │ 4.STUN看到: │ │ │ "包来自203.0.113.25:54321" │ │ │ │ │ │ 5.回复: │ │ │ "你的地址是203.0.113.25:54321" │ │◄───────────────────┤ │ │ │ │ │ 6.NAT反向转换 │ │ │ 公网:203.0.113.25:54321│ │ │ → 内网:192.168.1.100:12345│ │ │ │ │ 7.收到回复 │ │ │ "你是203.0.113.25:54321"│ │ │◄─────────────────┤ │ │ │ │
NAT的核心作用:地址转换器
NAT(网络地址转换)是你的路由器在做的事情:
1.NAT解决了什么问题?
IPv4地址不足:公网IP不够用,你家只有一个公网IP
多个设备共享:你家的手机、电脑、平板都通过这一个公网IP上网
2.NAT如何工作?
你的家: ┌─────────────────────────────────┐ │ NAT路由器 │ │ 公网IP:203.0.113.25 │ ├─────────┬─────────┬─────────────┤ │ 你的手机 │ 你的电脑 │ 你的平板 │ │192.168.1.100 192.168.1.101 192.168.1.102│ └─────────┴─────────┴─────────────┘ NAT映射表(路由器的记忆): ┌─────────────────┬─────────────────────┐ │ 内网地址:端口 │ 公网地址:端口 │ ├─────────────────┼─────────────────────┤ │192.168.1.100:12345│203.0.113.25:54321 │ ← 你的STUN请求 │192.168.1.101:80 │203.0.113.25:80 │ ← 网页浏览 │192.168.1.102:443 │203.0.113.25:443 │ ← 其他应用 └─────────────────┴─────────────────────┘
3.为什么你需要STUN来知道这个地址?
因为:
你的设备只知道:
192.168.1.100:12345(内网地址)路由器知道:
192.168.1.100:12345↔203.0.113.25:54321(映射)STUN服务器看到:
203.0.113.25:54321(公网地址)
你无法从自己设备上知道NAT后的公网地址,必须问外部的STUN服务器。
完整流程:从STUN到P2P连接
整个P2P建立过程: ┌──────┐ 1.问STUN ┌──────┐ 2.交换地址 ┌──────┐ │ 你 │───────────────►│ STUN │◄───────────────│朋友 │ │ │◄───────────────│ │───────────────►│ │ │ │ "你是A" └──────┘ "你是B" │ │ └──┬───┘ └──┬───┘ │ │ │ 3.告诉微信:"我是A" │ 4.告诉微信:"我是B" │ │ └─────────────────────┐ ┌─────────────────┘ │ │ ▼ ▼ ┌──────────┐ │微信服务器│ └────┬─────┘ │ ┌───────────────────────┼─────────────────────┐ │ 5.微信告诉你:"朋友是B" │ 6.微信告诉朋友:"你是A"│ ▼ │ ▼ ┌──────┐ │ ┌──────┐ │ 你 │ │ │朋友 │ │ A │────────────────────┼───────────────────►│ B │ │ │◄───────────────────┼────────────────────│ │ │ 知道B │ 7.尝试P2P连接 │ 8.响应连接 │ 知道A │ └──────┘ │ └──────┘
关键总结
STUN不知道你要和谁通话:它只是回答“我看到你的地址是X”
NAT创造了这个问题:因为你的设备在内网,看不到自己的公网地址
STUN解决了这个问题:作为外部观察者,告诉你NAT后的地址
地址交换需要微信服务器:STUN只告诉你地址,交换地址需要微信服务器协调
打个比方:
NAT= 邮局分拣员(把你的门牌号换成街道地址)
STUN= 问路人(“请问我现在的街道地址是什么?”)
微信服务器= 电话接线员(帮你们交换地址信息)
所以,STUN和NAT是因果关系:因为NAT隐藏了你的真实公网地址,才需要STUN来发现它。而这一切都与“你要和谁通信”完全无关。