第二章:WebRTC基础概念:实时通信原理、NAT穿透与STUN/TURN、SDP协议详解
好,咱们正式开始啃硬骨头了。这一章,我会把WebRTC最核心的三个概念掰开揉碎讲清楚。实时通信原理、NAT穿透、SDP协议——这三样东西,你搞懂了,后面写代码就是水到渠成的事。
2.1 实时通信的本质:不就是传数据吗?
实时通信,说白了就是让两个端点之间能「瞬间」交换音视频数据。但这里有个坑——互联网不是为实时通信设计的。它最初是为了发邮件、传文件,丢几个包重传就行,延迟几秒钟无所谓。
但实时通信不行。你想想看,视频通话里卡顿半秒,对方的表情就僵住了,体验极差。
所以WebRTC做了几件关键的事:
- UDP优先:TCP虽然可靠,但重传机制会导致延迟不可控。WebRTC默认走UDP,丢包了?直接跳过,或者用FEC(前向纠错)补回来。
- 端到端加密:所有音视频数据默认加密,中间节点无法窥探内容。这是强制性的,你关不掉。
- 自适应码率:网络变差了,自动降低画质,保证通话不中断。我做过一个项目,用户从WiFi切到4G,画面瞬间模糊了一下,但没断——这就是自适应在起作用。
核心要点:WebRTC不是发明了新的传输协议,而是把UDP、DTLS、SRTP这些现有技术组合起来,专门为实时场景做了优化。
2.2 NAT穿透:为什么两个设备互相找不到?
这是新手最容易懵的地方。你写了一个WebRTC应用,在本地跑得好好的,一放到公网就连不上。为什么?
因为大多数设备都在NAT后面。NAT(网络地址转换)是路由器干的事——它把内网IP(比如192.168.1.100)映射成一个公网IP加一个端口。问题是,这个映射是临时的,外部设备不知道你的内网地址,也没法主动连你。
这就好比你在公司内网,别人从外网给你打电话,但总机不转接——电话永远打不通。
WebRTC解决这个问题的思路很巧妙:它让两个设备先通过一个「中间人」交换各自看到的公网地址,然后尝试直接连接。这个中间人就是信令服务器。
但光有信令还不够。NAT有好几种类型,有些NAT很「严格」,不允许外部主动连接。这时候就需要STUN和TURN上场了。
2.3 STUN与TURN:打洞与中继
这两个东西经常被放在一起说,但作用完全不同。
2.3.1 STUN:帮我看看我的公网地址
STUN(Session Traversal Utilities for NAT)做的事情很简单:客户端向STUN服务器发一个请求,服务器返回「我看到你的公网IP和端口是xxx」。这样客户端就知道自己在公网上的「身份」了。
然后客户端把这个地址通过信令发给对方,对方尝试直连。如果NAT类型不严格,这个直连就能成功——这就是所谓的「打洞」。
但STUN不是万能的。我记得有一次做跨国项目,中国的用户和美国的用户怎么也连不上。查了半天,发现两边都是对称NAT——这种NAT下,STUN打洞基本无效。
我的经验:对称NAT是STUN的克星。如果你发现用户经常连不上,先检查NAT类型。可以用stunclient工具测试。
2.3.2 TURN:最后的保底方案
当STUN打洞失败时,TURN(Traversal Using Relays around NAT)就派上用场了。TURN服务器充当一个中继——两边的数据都先发给TURN服务器,再由服务器转发给对方。
代价是什么?延迟增加、带宽消耗翻倍。TURN服务器需要处理所有音视频数据,成本很高。所以TURN是最后的选择,能不用就不用。
我见过一些团队,一上来就配TURN,结果服务器带宽爆了,账单吓人。正确的做法是:先用STUN尝试直连,失败后再回退到TURN。
避坑指南:我曾经在一个项目中,TURN服务器配置了但没开端口转发,结果所有流量都走TURN,延迟飙升到500ms。检查配置时一定要确认端口可达。
2.4 SDP协议:通话的「简历」
SDP(Session Description Protocol)不是传输数据的协议,它是用来描述「这次通话长什么样」的。你可以把它理解成一份简历——上面写着:
- 我用什么编码(H.264?VP8?)
- 我的IP和端口是多少
- 我要传音频还是视频,还是两者都有
- 加密参数是什么
在WebRTC中,SDP通过信令通道交换。一端创建Offer(提议),另一端创建Answer(应答)。这个过程叫做「协商」。
下面是一个简化版的SDP示例:
v=0
o=- 123456 2 IN IP4 192.168.1.100
s=-
t=0 0
m=audio 49170 RTP/AVP 0 8 97
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 opus/48000/2
m=video 49172 RTP/AVP 96 98
a=rtpmap:96 H264/90000
a=rtpmap:98 VP8/90000
你看,这里明确写了音频用PCMU或Opus,视频用H.264或VP8。双方协商后,选一个都支持的编码。
实际开发中,你不需要手动写SDP——浏览器会帮你生成。但理解SDP的结构很重要,因为调试时经常需要看SDP内容来排查问题。
2.5 三者如何配合?一张图说清楚
我把整个流程画了一张图,你看完就明白了:
流程总结一下:
- 双方通过信令服务器交换SDP(包含各自的媒体能力)
- 各自向STUN服务器查询公网地址
- 通过ICE框架尝试多种路径直连
- 如果直连失败,启用TURN中继
整个过程对开发者来说是透明的——你只需要调用createOffer()、setLocalDescription()这些API,底层逻辑浏览器帮你做了。
2.6 小结
这一章的内容偏理论,但非常重要。我见过太多人一上来就写RTCPeerConnection,结果连不上也不知道为什么。现在你知道了:连不上,大概率是NAT穿透的问题。先查STUN/TURN配置,再看SDP是否协商成功。
下一章我们会动手写一个完整的点对点视频通话demo。到时候你会看到这些概念是怎么落地的。
一句话记住:SDP负责「谈好怎么传」,STUN/TURN负责「找到路」,ICE负责「选最优的路」。