SIP ——了解PRACK

本文详细阐述了SIP协议中临时应答的可靠传输机制,通过引入PRACK方法来确保与PSTN交互过程中的消息可靠性,并讨论了UAS和UAC在实现可靠临时响应的行为差异及构建方法。
部署运行你感兴趣的模型镜像
概述
SIP定义了两种应答:临时(provisional)和最终(final)。
最终应答传送的是请求处理的结果,是可靠性的(reliably)。 而临时应答传送的是处理过程的信息,由RFC3261是非可靠的。
但是由现在的情况看来,特别是与PSTN交互过程中发现:临时应答也应该是可靠的。

RFC3262定义了一种SIP可选的扩展方法——PRACK(provisional ack),用于支持临时应答的可靠性。它的实现机制如下:
借鉴了INVITE请求的2**应答的可靠性机制:通过构造新的事务来重发ACK来确认接收到了2**应答,这种可靠性是端点到端点(end-to-end)的。对于1**(除100外)的应答,使用PRACK来终止该应答的重 发。PRACK是对临时应答而言,不同于ACK,是一种跟BYE一样的正常SIP消息。所以它的可靠性是点到点(hop-by-hop)的,且具有 应答。

每个临时响应都有一个顺序号,在于RSeq头域中。而PRACK消息包括了RAck头域,指示回应的临时相应的顺序号,且不具有积累效果。


UAS行为
如果请求INVITE的头域Supported中包括选项100rel,UAS可能发送可靠性临时响应;如果请求INVITE的头域Require中包括选项100rel,UAS必须发送可靠性临时响应,否则发送420 (Bad Extension)且Unsupported头域中包括选项100rel。
但是,如果请求中不满足以上任一情况,则不能支持可靠临时相应。

UAS需要发送可靠临时相应原因:
多种原因。其中之一为根据RFC3261,如果UAS需要一段时间来处理请求,UAS需要发送临时相应消息给Proxies来“延时(extention)”,因为Proxy一般只保留请求上下文3分钟,所以为了避免丢失消息,常需要1分钟重发一次。而使用可靠临时相应只需2分半钟重发一次。

可靠临时响应的构建:
只需在RFC3261的基础上进行一些补充:必须包括Require头域(包括100rel选项)和RSeq头域(值为1到2**32-1,是对话中是唯一的)。

PRACK和临时响应的匹配:
PRACK首先必须和临时相应在同一个对话之中,RAck中的方法、CSeq-num和response-num分别对应于临时响应CSeq中的方法、CSeq中的序号和RSeq的序号。

如果接受到的PRACK无法找到相匹配的临时相应,则回应481;否则回应2**,并停止该临时相应的重发。
如果在64*T1时间内没有接收到PRACK,则UAS回应5**。
在第一个可靠响应得到回应,才可以发送第二个可靠相应。对于同一个请求,第二个可靠相应的RSeq比第一个大1。

UAS可以在可靠临时响应未收到PRACK情况下发送最终应答,除了以下情况:最终响应为2**且其中一个临时相应中有媒体描述。如果最终响应已经发送,则临时相应的重发和新的临时消息发送都不能进行。


UAC行为
如果需要可靠临时应答,则在INVITE请求的Require头域中包含100rel选项,而其他方法中的Require中不能包含该选项;如果将可靠临时应答的需求的决定权交给UAS,则应在INVITE的头域Supported中包含100rel选项。
当头域Require中包含100rel的临时消息到来时,且临时消息非100,说明临时消息是可靠的。UAC接下来在对话中建立PRACK请求,跟其它在对话中建立的非INVITE请求一样,UAC不应在接收到重发的可靠临时应答时重发PRACK,即使重发不会引起协议错误。

一个临时应答到来时,如果dialog ID、CSeq、 和RSeq跟之前的一样时,该应答视为重发,该应答必须被丢弃。所以,UAC需要记录RSeq值直到最终应答的到来。
如果新的一个临时应答到来时,需要判断RSeq是否比之前的值大。如果不是的话,则不能回应PRACK,可以丢弃该临时应答或缓存起来以等待没有到来的老的临时应答。

如果在最终应答到来之后收到临时应答,可以回应或直接丢弃。


Offer/Answer模型和PRACK方法
(详见RFC3262或之后的关于Offer/Answer的文章)


1)RFC3262中不支持除INVITE外其它方法的可靠性临时响应,除非是能建立对话的扩展方法。
2)UAS不能发送可靠的100临时相应。因为100响应一般是hop-by-hop的,即消息的可靠性在于hop的两端之间,而不在于端到端之间;而这里实现的可靠性是端到端之间的,即接受消息初始发送和最终接受方,能满足消息真正交互成功。但是PRACK的可靠性又是hop-by-hop的,即PRACK方法的消息交互依靠的是hop之间的确认。


参考

RFC3262

转自 http://blog.sina.com.cn/s/blog_4b839a1b010082xy.html

另外可以参考 http://wenku.baidu.com/view/5b291a620b1c59eef8c7b403.html

您可能感兴趣的与本文相关的镜像

Yolo-v8.3

Yolo-v8.3

Yolo

YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

<think> 我们正在讨论SIP协议中的183响应和PRACK请求。首先,SIP(Session Initiation Protocol)是用于建立、修改和终止多媒体会话的协议。在SIP中,183响应(会话进行中)是一个临时响应,通常用于表示呼叫正在被处理,例如正在回铃。 在SIP中,当UAC(User Agent Client)发送一个INVITE请求,UAS(User Agent Server)可能会发送一系列1xx临时响应,然后是最终响应(2xx, 3xx, 4xx, 5xx, 6xx)。临时响应并不终结INVITE事务。其中,100到199的响应都是临时响应。 特别地,183响应通常用于传递呼叫进程信息,比如回铃音。但是,对于某些临时响应(100除外),如果它们包含消息体(例如SDP描述),那么这些响应被认为是“可靠”的临时响应。根据RFC3262,可靠临时响应需要被确认,以防止消息丢失导致的问题。确认的方式就是使用PRACK(Provisional Response ACKnowledgement)方法。 因此,问题:SIP 183响应一定要回复PRACK吗? 答案是:不一定,取决于183响应是否是一个可靠临时响应。如果183响应中包含了Require头字段,并且该头字段的值包含“100rel”(表示要求可靠临时响应机制),那么UAC必须用PRACK请求来确认这个响应;否则,不需要。 具体来说: - 如果UAS在发送183响应时,希望该响应被可靠地传递,它会在响应中包含一个Require头字段,其值为“100rel”,并且还会包含一个RSeq头字段(用于序号)。 - UAC收到这样的183响应后,必须发送PRACK请求(其中包含RAck头字段,其值由RSeq和CSeq组成)来确认。 - 如果183响应没有包含Require: 100rel,那么UAC不需要发送PRACK。 所以,是否回复PRACK,取决于183响应中是否要求了可靠临时响应机制(通过Require: 100rel指示)。 下面我们来看一个例子: 场景:UAS发送了一个183响应,要求可靠性: ``` SIP/2.0 183 Session Progress Via: SIP/2.0/UDP client.atlanta.com:5060;branch=z9hG4bK74bf9 From: Alice <sip:alice@atlanta.com>;tag=9fxced76sl To: Bob <sip:bob@biloxi.com>;tag=8321234356 Call-ID: 3848276298220188511@atlanta.com CSeq: 1 INVITE Require: 100rel RSeq: 9021 Content-Type: application/sdp Content-Length: ... (SDP body omitted) ``` 此时,UAC必须回复PRACK请求,该请求看起来像这样: ``` PRACK sip:bob@biloxi.com SIP/2.0 Via: SIP/2.0/UDP client.atlanta.com:5060;branch=z9hG4bK72ghjs From: Alice <sip:alice@atlanta.com>;tag=9fxced76sl To: Bob <sip:bob@biloxi.com>;tag=8321234356 Call-ID: 3848276298220188511@atlanta.com CSeq: 2 PRACK // 注意,CSeq序列号增加了,并且方法是PRACK RAck: 9021 1 INVITE // 确认RSeq为9021,并且对应的CSeq是1 INVITE Content-Length: 0 ``` 如果183响应中没有Require: 100rel,则不需要发送PRACK。 总结: - 当183响应中包含Require: 100rel时,UAC必须回复PRACK。 - 如果183响应中没有Require: 100rel,则不需要回复PRACK。 因此,不是所有的183响应都需要回复PRACK,只有那些要求可靠传输的183响应才需要。 相关问题: §§相关问题§§: 1. 在SIP中,哪些临时响应需要可靠传输?为什么需要可靠传输? 2. PRACK请求是如何确保可靠传输的? 3. 如果UAC没有收到183响应,会有什么后果?如果要求可靠传输(Require:100rel)但没有收到PRACK,UAS会怎么做? 4. 除了PRACKSIP中还有哪些请求用于确认响应? </think> 在 SIP 协议中,**183 Session Progress 响应不一定需要回复 PRACK**,这取决于响应中是否包含 `Require: 100rel` 头字段以及具体会话场景。以下是详细说明: --- ### 1. **是否需要回复 PRACK 的判断依据** - **需要回复 PRACK 的情况** 如果 183 响应中包含 `Require: 100rel` 头字段(表示要求可靠临时响应机制),则 UAC(User Agent Client)必须回复 PRACK 请求以确认收到该响应。 示例响应头: ``` SIP/2.0 183 Session Progress Require: 100rel // 关键标志 RSeq: 12345 // 响应序列号 ...其他头字段... ``` - **无需回复 PRACK 的情况** 如果 183 响应中**没有** `Require: 100rel`,则 UAC 无需回复 PRACK。这是常见场景,例如基本呼叫流程中的振铃提示。 --- ### 2. **PRACK 的作用与流程** 当需要可靠传输时,PRACK 的交互流程如下: ```plaintext UAC UAS | INVITE | |------------------------>| | 183 (Require:100rel)| |<------------------------| | PRACK | // UAC 必须回复 PRACK |------------------------>| | 200 OK (PRACK) | |<------------------------| | 180 Ringing | // 后续响应 |<------------------------| ``` --- ### 3. **PRACK 请求的代码实现示例(Java + JAIN-SIP)** 以下是使用 Java 和 JAIN-SIP 库回复 PRACK 的代码片段: ```java import javax.sip.*; import javax.sip.message.*; public void handle183Response(Response response) { // 检查是否需要 PRACK if (response.getHeader(RequireHeader.NAME) != null) { RequireHeader require = (RequireHeader) response.getHeader(RequireHeader.NAME); if (require.getOptionTag().equalsIgnoreCase("100rel")) { // 构造 PRACK 请求 Request prack = createPrackRequest(response); sipClient.sendRequest(prack); } } } private Request createPrackRequest(Response response) { // 从响应中提取必要信息 RAckHeader rackHeader = createRackHeader( response.getHeader(RSeqHeader.NAME).getSeqNumber(), response.getHeader(CSeqHeader.NAME).getSeqNumber(), response.getHeader(CSeqHeader.NAME).getMethod() ); // 构造 PRACK 请求 Request prack = messageFactory.createRequest( "PRACK", response.getHeader(ToHeader.NAME).getAddress().getURI() ); // 设置关键头字段 prack.addHeader(rackHeader); prack.addHeader(response.getHeader(CallIdHeader.NAME)); prack.addHeader(response.getHeader(FromHeader.NAME)); prack.addHeader(response.getHeader(ToHeader.NAME)); prack.addHeader(response.getHeader(ViaHeader.NAME)); return prack; } ``` **代码解释**: 1. `handle183Response` 检测 `Require: 100rel` 头字段,决定是否发送 PRACK。 2. `createPrackRequest` 构造 PRACK 请求,其中: - `RAckHeader` 包含从 183 响应中提取的 `RSeq` 和 `CSeq` 值。 - 其他头字段(如 `Call-ID`、`From`、`To`)需与原始 INVITE 一致。 3. PRACK 是独立事务,因此需要新的 CSeq 值(方法名设为 `PRACK`)。 --- ### 4. **关键注意事项** - **可靠性机制**:PRACK 是 RFC 3262 定义的可靠性机制,用于确保临时响应(如 183)在不可靠网络中的传输。 - **超时重传**:若 UAS(User Agent Server)未收到 PRACK,会重传 183 响应(通常间隔 500ms、1s、2s...)。 - **兼容性**:如果 UAC 不支持 PRACK,应拒绝会话(回复 420 Bad Extension)。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值