在 IMS/VoNR 体系中,一次成功的 INVITE 会在主被叫 UE 之间建立一条 SIP 对话(Dialog)。这条对话由三元组 (Call-ID, From-tag, To-tag) 唯一标识,并伴随一套已协商好的媒体参数(SDP offer/answer 结果)。然而通话一旦建立,业务远未结束:用户按"保持键"挂起对端、从纯语音升级到音视频通话、网络侧因会话定时器到期需要刷新、或者无线侧因编解码不匹配需要重协商——所有这些"在不拆掉现有对话的前提下、修改正在进行的会话参数"的操作,都依赖同一个核心信令:Re-INVITE。
Re-INVITE 并非一个新的方法(Method),它就是普通的 INVITE,只不过它被发送在一个已经存在的 Dialog 之内。3GPP 在 TS 24.229《IP multimedia call control protocol based on SIP and SDP; Stage 3》 中专门用 Section 6.1.4 "Session modification" 一整节来规范它的行为,下设三个子句:
Re-INVITE 的本质可以用一句话概括:复用既有 Dialog 的路由集合与对话标识,递增 CSeq,携带一份新的 SDP offer,触发一次完整的 offer/answer 重协商。它是 IMS 补充业务(Call Hold、Call Resume、Call Upgrade/Downgrade)、Session Timer 保活、动态 QoS 重协商统一承载的信令底座。理解它,就理解了 IMS 通话"建立之后"的全部动态行为。
Re-INVITE 之所以"轻量",关键在于它复用了初次 INVITE 谈成的全部对话上下文。具体表现为四个不变与一个必变:
Route 头里记录的 P-CSCF/S-CSCF 链路转发,无需重新做 DNS 解析与服务路由发现。CSeq 的序号部分必须严格单调递增,方法名保持 INVITE。任何对端收到 CSeq 不大于已处理序号的 re-INVITE,都会回 500 Server Internal Error 或直接丢弃。SDP offer/answer 模型(RFC 3264)在 Re-INVITE 中有一个极易被忽视的规则:新的 offer 必须完整描述整个会话,而不是只描述变化的部分。也就是说,即便你只想新增一条视频流,offer 里仍要包含原有的音频 m= 行。这支持无状态代理(stateless proxy)转发和错误恢复。此外,offer 的提供方可以是任意一侧——既可由主叫侧(原 UAC)发起,也可由被叫侧(原 UAS)通过发送一个不带 SDP 的 re-INVITE 来反向请求对端给出新 offer。
下面以主叫 UE-A 将被叫 UE-B 置于保持(Call Hold) 为例,画出 Re-INVITE 穿越整个 IMS 核心网的完整信令链。该流程严格遵循 TS 24.229 第 5.7 节(主叫侧)与第 6.2/6.3 节(P-CSCF/S-CSCF)的处理规则:
sequenceDiagram
autonumber
participant UEa as 主叫 UE-A
participant PCSCFa as P-CSCF-A
participant SCSCFa as S-CSCF-A
participant AS as TAS / AS
participant SCSCFb as S-CSCF-B
participant PCSCFb as P-CSCF-B
participant UEb as 被叫 UE-B
Note over UEa,UEb: 已建立 VoNR 会话,处于 Confirmed 状态
UEa->>PCSCFa: INVITE(re-INVITE) CSeq+1, SDP offer(a=sendonly)
Note right of PCSCFa: 6.2:SDP 授权校验<br/>Rx 更新 QoS(5QI=1 方向)
PCSCFa->>SCSCFa: INVITE(re-INVITE)
SCSCFa->>AS: INVITE(命中 iFC,触发 Hold 补充业务)
AS-->>SCSCFa: INVITE(透传/放音指示)
SCSCFa->>SCSCFb: INVITE
SCSCFb->>PCSCFb: INVITE
PCSCFb->>UEb: INVITE(re-INVITE) a=sendonly
Note left of UEb: 6.1.4.3:接收 offer<br/>本地媒体方向置为 recvonly
UEb-->>PCSCFb: 200 OK (SDP answer a=recvonly)
PCSCFb-->>SCSCFb: 200 OK
SCSCFb-->>SCSCFa: 200 OK
SCSCFa-->>PCSCFa: 200 OK
Note right of PCSCFa: 确认 Rx 资源<br/>charging 透传 ICID
PCSCFa-->>UEa: 200 OK
UEa-->>UEb: ACK(端到端,完成事务)
Note over UEa,UEb: 对话存活,媒体变为单向(UEa 停发只收)
关键设计意图说明:
Session-Expires。Re-INVITE 携带的 SDP offer 是整个机制的"数据载荷"。以 Call Hold 为例,UE-A 发出的 offer 关键 IE 如下:
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP [UEa_IP]:PORT;branch=z9hG4bK...new
Route: <sip:pcscf_a;lr>, <sip:scscf_a;lr>
Call-ID: a1b2c3d4@uea (与原会话相同)
From: <sip:user_a...>;tag=7777 (与原会话相同)
To: <sip:user_b...>;tag=8888 (与原会话相同)
CSeq: 3 INVITE (递增: 原 CSeq=2)
Session-Expires: 1800;refresher=uac (会话定时器)
Require: 100rel, precondition
Content-Type: application/sdp
v=0
o=- 2890844526 2890844527 IN IP4 UEa_IP (version号必须递增)
c=IN IP4 UEa_IP
m=audio 49170 RTP/AVP 96 97 (媒体行不变)
a=curr:qos local sendrecv (当前本地QoS已满足)
a=curr:qos remote sendrecv (当前远端QoS已满足)
a=des:qos mandatory local sendrecv
a=des:qos mandatory remote sendrecv
a=sendonly (★保持:方向改为只发不收)
a=rtpmap:96 EVS/...
被叫侧的 answer 关键差异仅在 a=recvonly(被叫只能收不能发,配合主叫只发不收,于是双向媒体实际停摆),形成"伪单工"。下表归纳 IMS 中常用的媒体方向语义:
| SDP 方向属性 | 主叫侧语义 | 被叫侧应答 | 典型业务场景 |
|---|---|---|---|
a=sendrecv |
双向收发 | a=sendrecv |
正常通话/Resume |
a=sendonly |
只发不收 | a=recvonly |
Call Hold(RFC 6337 推荐) |
a=recvonly |
只收不发 | a=sendonly |
监听/会议旁听 |
a=inactive |
既不发也不收 | a=inactive |
全媒体挂起/双向保持 |
c=IN IP4 0.0.0.0 |
连接地址无效 | 任意 | Legacy Hold(RFC 2543,已弃用) |
设计要点:RFC 6337 明确弃用了
c=0.0.0.0这种"用非法地址表示保持"的老做法,推荐用a=sendonly/a=inactive。但在现网抓包中,仍能见到某些老 SBC/终端混用c=0.0.0.0。若主叫发c=0.0.0.0而被叫按现代规范回a=recvonly,会导致 RTP 流向一个不存在的地址,表现为"保持后仍有单向杂音"。
TS 24.229 6.1.4.2 给出了一段非常关键、却又容易被误读的 precondition 处理规则,可以用下面的决策流精确还原:
flowchart TD
S[re-INVITE 会话修改请求] --> Q1{是否使用\nprecondition 机制?}
Q1 -- 否 --> O1[SDP 无 QoS 状态属性\n直接 offer/answer]
Q1 -- 是 --> Q2{QoS 需求是否增加?\n新增媒体流/更高带宽编解码}
Q2 -- 否<br/>如:呼叫保持 --> M1[local 与 remote 的 QoS\n均标记为 met 已满足]
Q2 -- 是<br/>如:呼叫升级加视频 --> M2[按 6.1.2 初始流程\n本地 curr=none, des=mandatory]
M1 --> OUT[发送 re-INVITE/UPDATE/PRACK]
M2 --> PRE[触发 183 + PRACK + UPDATE\n等待 QoS 确认]
PRE --> OUT
O1 --> OUT
OUT --> FAIL{网络资源修改/预留失败?}
FAIL -- 是 --> CAN[发送 CANCEL 终止本次修改]
FAIL -- 否 --> DONE[200 OK + ACK, 完成]
这段逻辑的精髓在于区分两类修改:
local 和 remote 的当前 QoS 都直接标记为 met(已满足)。这意味着不需要再等待任何资源预留确认,对端收到后可以直接回 200 OK,整个修改一步到位,信令开销最小。none、期望状态写 mandatory,从而触发标准的 183 → PRACK → 资源确认 → UPDATE → 200 完整交互链。这是因为新媒体流需要重新建立专用 QoS Flow/承载,必须等资源真正就绪后才能宣称"已满足"。最后一道保险:如果网络侧资源修改或预留失败,UE 必须(shall)发送 CANCEL 来终止本次会话修改,回退到原会话参数,而不是把会话搞挂。这是 IMS 容错设计的体现。
Re-INVITE 引出了一个 SIP 特有的竞态问题——Glare(眩光冲突)。当主被叫两侧在几乎同一时刻各自发出一个 re-INVITE(或 re-INVITE 与 UPDATE),且对方尚未收到本端的请求时,双方就陷入了"各自有一个 pending 的 INVITE 事务、又各收到对端一个 INVITE"的僵局。SIP 不允许在同一个 Dialog 内同时存在两个 pending 的 INVITE 事务(会话状态机无法确定以谁的 offer 为准)。
RFC 3261 Section 14.2 规定:当 UAS 收到一个 INVITE 请求,而该 Dialog 内已有一个 INVITE 客户端事务处于 Proceeding/Completed 状态时,UAS 必须(MUST)回 491 Request Pending。冲突化解靠的是随机回退(Randomized Backoff):
flowchart TD
A[UE-A 发送 re-INVITE-A] --> B{对端是否已有\npending INVITE 事务?}
B -- 否 --> C[正常处理: 183/200]
B -- 是 --> D[返回 491 Request Pending]
D --> E[随机回退 2.1 ~ 4 秒]
E --> F[重新发送 re-INVITE-A']
C --> G[200 OK + ACK 会话更新]
F --> C
随机区间 2.1s–4s 的设计非常巧妙:它避免了两侧退避相同时间后再次同时重发、再次冲突的死循环。由于双方退避时间不同,几乎必然会错开重发窗口。需要强调的是,在 3GPP IMS 中,S-CSCF/P-CSCF 作为有状态代理(stateful proxy),会忠实地把 491 透传回原发方,不会自己吞掉或改写——这也是为什么 Glare 问题在端到端抓包中清晰可见。
实务中 Glare 高发于两种场景:一是 Session Timer 到期时两侧同时刷新;二是补充业务(如 Call Hold)与网络侧主动发起的媒体重协商撞车。优秀的 IMS 终端实现会在收到 491 后严格按随机退避重试,而劣质实现可能直接放弃,表现为"保持操作偶发失败"。
从协议状态机的角度看,Re-INVITE 让会话在 Confirmed(已确认)与 Modifying(修改中)状态间往返。下图标出了所有合法转移,包括 precondition 子状态与失败回退路径:
stateDiagram-v2
[*] --> Confirmed: 初次 INVITE 建立成功
Confirmed --> Modifying: 发送/接收 re-INVITE(含 offer)
Modifying --> Modifying_Early: 触发 precondition\n(183+PRACK+UPDATE)
Modifying_Early --> Confirmed: 200 OK + ACK
Modifying --> Confirmed: 200 OK + ACK\n(无需 precondition)
Modifying --> Terminating: CANCEL\n(资源修改/预留失败)
Terminating --> Confirmed: 回退原会话参数
Confirmed --> Glare: 收到 491\n(对端有 pending 事务)
Glare --> Modifying: 随机回退后重发 re-INVITE
Confirmed --> [*]: BYE 释放
这张状态机是排错时定位问题的"地图":当一次 Hold 失败,首先要回答的问题是——会话当前到底卡在 Modifying 还是 Modifying_Early?前者说明卡在 200 OK/ACK,多半是 P-CSCF 的 Rx 授权或端到端 ACK 丢失;后者说明卡在 precondition 的 QoS 确认,多半是无线侧 QoS Flow 没建立起来。
如何在一次 Wireshark 抓包中识别 Re-INVITE 链? 关键判据有四:
CSeq 方法名为 INVITE 且序号比已建立会话大——这就是 re-INVITE 的指纹。Via 头的 branch 参数以 z9hG4bK 开头且为新值(RFC 3261 魔数,用于事务区分)。200 OK 与 ACK,三者构成一个完整事务。a=sendonly、新增 m=video 行、Session-Expires 刷新)即本次修改的语义。| 常见故障现象 | 根因定位思路 | 涉及网元/接口 |
|---|---|---|
| Hold 后对端仍能听到背景音 | 主叫发 a=sendonly 但本地 RTP 仍在上行;或被叫未按 RFC 6337 应答 a=recvonly |
UE 媒体栈 / SBC |
| Hold 操作偶发失败、报 491 | Glare 冲突,终端未做随机退避重试 | UE SIP 栈 |
| Call Upgrade 加视频失败 | precondition 未满足,UPDATE 未发出或 Rx 未授权 5QI=2 |
P-CSCF↔PCF(Rx) / 无线 QoS Flow |
| 会话静默掉线(无 BYE) | Session Timer 失效,两侧都没刷新且未检测到失效 | UE / P-CSCF 会话定时 |
| re-INVITE 后无 ACK,会话悬挂 | 端到端 ACK 被 NAT/SBC 丢弃,事务超时 | P-CSCF / SBC |
a=sendonly(现代规范);部分老款 SBC 和企业 PBX 仍用 c=0.0.0.0,混用时易出单向杂音。UPDATE(RFC 3311)刷新。若对端不支持 UPDATE 刷新,会退化为 re-INVITE。Q1:Re-INVITE 和 UPDATE 都能改会话,区别是什么?
A:二者都能携带 SDP 做 offer/answer 重协商,区别在于事务语义。Re-INVITE 用于 Confirmed 状态(对话已建立后) 的会话修改;UPDATE(RFC 3311)则主要用于 Early Dialog(早期对话,即 200 OK 之前) 的早期媒体参数更新(如更新 precondition 的 QoS 状态),也可在确认后用于轻量刷新。Re-INVITE 还能修改 Dialog 自身参数(如目标 URI),UPDATE 不能。会话定时器刷新两者皆可。
Q2:为什么 Call Hold 不需要重新做 QoS 预留?
A:因为按 TS 24.229 6.1.4.2,Hold 不抬升 QoS 需求(带宽、5QI 都不变,只是方向变更)。所以 offer 中 local/remote 当前 QoS 直接标记为 met,不触发 precondition 等待链,对端可直接回 200 OK,一步完成。
Q3:被叫侧如何主动发起媒体重协商? A:被叫(原 UAS)若想改媒体,可发送一个不含 SDP 的 re-INVITE,主叫收到后必须回一个带 SDP offer 的 200 OK,被叫再以 ACK 携带 answer。这是反向 offer 的标准玩法。也可直接由被叫发带 offer 的 re-INVITE(若它此前是 answer 方,则可"角色切换"为 offer 方)。
Q4:491 之外,Re-INVITE 还会遇到哪些冲突响应?
A:主要是 500 Server Internal Error(带 Retry-After)和 503 Service Unavailable(过载)。但 491 是唯一专门针对"同一 Dialog 内 pending INVITE 冲突"的标准响应,且是唯一明确要求随机退避重试的。其他响应更多是通用服务端故障。
Q5:Re-INVITE 期间的媒体怎么处理?
A:在 offer/answer 交换完成前,双方应维持旧媒体参数继续收发,直到收到新的 200 OK + ACK 后才切换。若 offer 把某流置为 a=inactive,则在该 answer 确认后该流停摆。整个修改是"平滑切换",不应中断正在进行的媒体。
本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
