3. SIP会话流程:从呼叫建立到释放的完整旅程
各位同学,今天我们来聊聊SIP协议最核心的部分——会话流程。说白了,就是两个终端怎么通过SIP协议完成一次通话。我做了这么多年SIP协议分析,发现很多新手都卡在这一块,觉得流程太复杂。其实没那么玄乎,咱们一步步拆解。
核心要点:SIP会话流程本质上就是「请求-响应」的对话模式。就像两个人打电话,先拨号(INVITE),对方振铃(180 Ringing),接起来(200 OK),然后开始通话。就这么简单。
3.1 典型的SIP呼叫建立流程(Alice呼叫Bob)
先看一个最基础的场景。Alice想给Bob打个电话。没有代理服务器,直接点对点通信。嗯,我在项目初期做原型验证时,就经常用这种拓扑结构。
Alice Bob
| |
|------- INVITE (SDP) -------->|
| |
|<------ 180 Ringing ----------|
| |
|<------ 200 OK (SDP) ---------|
| |
|---------- ACK -------------->|
| |
|========= RTP媒体流 ==========|
| |
这个流程看起来简单,但有几个关键点要注意:
- INVITE请求:Alice发起的第一个请求,里面携带了SDP描述体。SDP里有什么?说白了就是「我能用什么编码、我的IP和端口是多少」。我见过有人把SDP写错了,结果媒体流死活通不了。
- 180 Ringing:Bob的终端开始振铃了。注意,这不是最终应答,只是临时响应。
- 200 OK:Bob接起电话。这个响应里也带了SDP,是Bob的媒体能力。
- ACK:Alice确认收到200 OK。这里有个坑——ACK是最后一个请求,它不需要响应。
实战经验:我曾经遇到过一个案例,Alice发了INVITE后一直收不到180 Ringing。排查了半天,发现是Bob的终端配置了「自动应答」模式,直接回了200 OK。所以,别以为180 Ringing一定会出现。
3.2 注册流程
注册是SIP协议的基础。没有注册,用户就像没有电话号码一样。说白了,注册就是把你的SIP URI和当前的联系地址(IP:端口)绑定起来。
Alice Registrar Server
| |
|------- REGISTER ----------->|
| |
|<------ 401 Unauthorized ----|
| |
|------- REGISTER (Auth) ---->|
| |
|<------ 200 OK ---------------|
| |
为什么会有401?这是SIP的安全机制。第一次REGISTER不带认证信息,服务器返回401要求认证。第二次REGISTER带上摘要认证信息。我建议你记住这个模式——很多SIP协议交互都是这种「挑战-响应」的套路。
| 字段 | 说明 | 注意事项 |
|---|---|---|
| To | 被注册的用户标识 | 必须和From一致(首次注册) |
| Contact | 当前的联系地址 | 可以包含过期时间expires |
| Expires | 注册有效期(秒) | 默认3600,到期前需刷新 |
避坑指南:我曾经遇到过一个生产环境的问题——用户频繁掉线。查到最后发现是注册过期时间设置得太短(60秒),而网络偶尔有延迟,导致注册刷新失败。建议把expires设置在300-600秒之间,既保证及时性,又不会给服务器太大压力。
3.3 呼叫修改流程
通话过程中,有时候需要修改媒体参数。比如,从音频切换到视频,或者改变编码格式。这就是re-INVITE的用武之地。
Alice Bob
| |
|======= RTP媒体流 (G.711) ====|
| |
|------- re-INVITE (SDP) ---->|
| (提议切换到G.722) |
| |
|<------ 200 OK (SDP) ---------|
| (同意切换) |
| |
|---------- ACK -------------->|
| |
|======= RTP媒体流 (G.722) ====|
| |
re-INVITE和初始INVITE的流程几乎一样。但有个关键区别——re-INVITE是在已有对话中发送的。你想想看,如果Bob不同意切换怎么办?他可以在200 OK里带上自己支持的编码,双方协商一个都支持的。
核心原则:SDP协商遵循「offer/answer」模型。发起方提供offer,应答方返回answer。双方必须找到一个交集。如果找不到,媒体流可能会中断。我在项目中就见过因为编码不匹配导致的「单通」问题——一方能听到声音,另一方听不到。
3.4 呼叫释放流程
通话结束,总得有个体面的告别方式。SIP使用BYE请求来终止会话。
Alice Bob
| |
|======= RTP媒体流 ============|
| |
|---------- BYE ------------->|
| |
|<------ 200 OK ---------------|
| |
谁先挂断,谁就发BYE。收到200 OK后,对话就结束了。注意,BYE只能在已建立的对话中发送。如果还没建立对话就想取消,得用CANCEL。
实战细节:我记得有一次调试,发现BYE发出去后对方没回200 OK。查了抓包,原来是网络丢包了。SIP协议有重传机制——如果没收到响应,会按指数退避重传。但重传次数有限,超时后就会强制结束。所以,别指望BYE一定能成功送达。
3.5 通过代理服务器的呼叫流程
实际部署中,很少有点对点的通信。大多数场景都通过代理服务器。代理服务器负责路由、认证、计费等。说白了,它就是个中间人。
Alice Proxy Bob
| | |
|--- INVITE -------->| |
| |--- INVITE ------->|
| | |
| |<-- 180 Ringing ---|
|<-- 180 Ringing ----| |
| | |
| |<-- 200 OK --------|
|<-- 200 OK ---------| |
| | |
|--- ACK ----------->| |
| |--- ACK ---------->|
| | |
|============== RTP媒体流 ==============|
| | |
代理服务器在这里做了两件事:
- 路由转发:根据请求URI找到Bob的位置
- 记录路由:在Via和Record-Route头域中记录自己的地址
你可能会问,为什么RTP媒体流不经过代理?嗯,这是个好问题。早期设计时考虑过媒体流也经过代理,但那样会带来巨大的性能开销。所以,SIP协议的设计原则是「信令走代理,媒体直连」。当然,有些场景(如NAT穿透)需要媒体也经过代理,那就是TURN服务器的事了。
重要提醒:代理服务器分为有状态和无状态两种。有状态代理会记住每个对话的状态,无状态代理只负责转发。我建议在核心网元中使用有状态代理,因为它可以做更精细的控制(如计费、拦截)。但要注意,有状态代理的资源消耗更大。
3.6 本章小结
好了,这一章的内容就到这里。我们走完了SIP会话的完整生命周期——从注册到呼叫建立,再到修改和释放。你想想看,这些流程其实都是围绕着一个核心:请求-响应。只要抓住这个本质,SIP协议就不难理解。
我个人习惯在分析SIP问题时,先抓包看信令流程,再对照本章的流程图。这样能快速定位问题。下一章我们会深入SIP消息的格式和头域,那是更细粒度的内容。