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消息的格式和头域,那是更细粒度的内容。

专注资料整理