跳到主要内容

17. 事务

17 事务

SIP是一种事务协议:组件之间的交互在一系列独立的消息交换中进行.具体而言,SIP事务由单个请求和对该请求的任何响应组成,其中包括零个或多个临时响应和一个或多个最终响应.对于请求为INVITE的事务(称为INVITE事务),仅当最终响应不是2xx响应时,事务还包括ACK.如果响应为2xx,则ACK不被视为事务的一部分.

  这种分离的原因源于向UAC发送INVITE的所有200(OK)响应的重要性.要将它们全部交付给UAC,UAS独自承担责任


对于重传它们(见第13.3.1.4节),UAC单独负责用ACKACK它们(见第13.2.2.4节).由于此ACK仅由UAC重新传输,因此它实际上被视为自己的事务.

事务有客户端和服务器端.客户端称为客户端事务,服务器端称为服务器事务.客户端事务发送请求,服务器事务发送响应.客户端和服务器事务是嵌入在任意数量的元素中的逻辑函数.具体来说,它们存在于用户代理和有状态代理服务器中.考虑第4节中的例子.在本例中,UAC执行客户机事务,其出站代理执行服务器事务.出站代理还执行客户端事务,该事务将请求发送到入站代理中的服务器事务.该代理还执行客户机事务,客户机事务反过来将请求发送到UAS中的服务器事务.这如图4所示.

+---------+ +---------+ +---------+ +---------+ | +-+|Request |+-+ +-+|Request |+-+ +-+|Request |+-+ | | |C||------->||S| |C||------->||S| |C||------->||S| | | |l|| ||e| |l|| ||e| |l|| ||e| | | |i|| ||r| |i|| ||r| |i|| ||r| | | |e|| ||v| |e|| ||v| |e|| ||v| | | |n|| ||e| |n|| ||e| |n|| ||e| | | |t|| ||r| |t|| ||r| |t|| ||r| | | | || || | | || || | | || || | | | |T|| ||T| |T|| ||T| |T|| ||T| | | |r|| ||r| |r|| ||r| |r|| ||r| | | |a|| ||a| |a|| ||a| |a|| ||a| | | |n|| ||n| |n|| ||n| |n|| ||n| | | |s||Response||s| |s||Response||s| |s||Response||s| | | +-+|<-------|+-+ +-+|<-------|+-+ +-+|<-------|+-+ | +---------+ +---------+ +---------+ +---------+ UAC Outbound Inbound UAS Proxy Proxy

              图4:交易关系

无状态代理不包含客户端或服务器事务.事务存在于一端的UA或有状态代理和另一端的UA或有状态代理之间.就SIP事务而言,无状态代理实际上是透明的.客户端事务的目的是从嵌入客户端的元素接收请求(将该元素称为"事务用户"或TU;它可以是UA或有状态代理),并将请求可靠地传递给服务器事务.

客户端事务还负责接收响应并将其传递给TU,过滤掉任何响应重传或不允许的响应(例如对ACK的响应).此外,在INVITE请求的情况下,客户端事务负责为接受2xx响应的任何最终响应生成ACK请求.

类似地,服务器事务的目的是接收来自传输层的请求并将其传送到TU.服务器事务过滤来自网络的任何请求重新传输.服务器事务接受来自TU的响应,并将它们传递到传输层,以便通过网络进行传输.在INVITE事务的情况下,它吸收除2xx响应之外的任何最终响应的ACK请求.

2xx响应及其ACK接受特殊处理.此响应仅由UAS重新传输,其ACK仅由UAC生成.需要这种端到端的处理,以便调用者知道接受呼叫的整个用户集.由于这种特殊处理,2xx响应的重传由UA核心处理,而不是事务层.类似地,2xx的ACK生成由UA核心处理.路径上的每个代理仅将每个2xx响应转发给INVITE及其相应的ACK.

17.1 客户交易

客户端事务通过维护状态机提供其功能.

TU通过一个简单的接口与客户端事务通信.当TU希望启动一个新事务时,它会创建一个客户端事务,并向其传递要发送的SIP请求以及要发送的IP地址,端口和传输.客户端事务开始执行其状态机.有效的响应将从客户端事务传递给TU.

根据TU传递请求的方法,有两种类型的客户端事务状态机.一种处理INVITE请求的客户端事务.这种类型的机器称为INVITE客户端事务.另一种类型处理除INVITE和ACK之外的所有请求的客户端事务.这称为非INVITE客户端事务.没有ACK的客户端事务.如果TU希望发送ACK,它会将ACK直接传递给传输层进行传输.

INVITE事务与其他方法不同,因为它的持续时间延长.通常,需要人工输入才能响应INVITE.发送响应的长时间延迟需要三方握手.另一方面,其他方法的请求有望迅速完成.由于非INVITE事务依赖于双向握手,因此TUs应该立即响应非INVITE request.

17.1.1 INVITE客户交易

17.1.1.1 INVITE事务概述

INVITE事务由三方握手组成.客户端事务发送INVITE,服务器事务发送响应,客户端事务发送ACK.对于不可靠的传输(如UDP),客户端事务以从T1秒开始并在每次重新传输后加倍的间隔重新传输请求.T1是对往返时间(RTT)的估计,默认值为500毫秒.这里描述的几乎所有事务计时器都使用T1进行缩放,更改T1会调整它们的值.请求不会通过可靠的传输重新传输.在收到1xx响应后,任何重新传输都将完全停止,客户端将等待进一步的响应.服务器事务可以发送额外的1xx响应,而服务器事务不能可靠地传输这些响应.最后,服务器事务决定发送最终响应.对于不可靠的传输,该响应会定期重新传输,而对于可靠的传输,则只发送一次.对于在客户端事务处接收到的每个最终响应,客户端事务发送一个ACK,其目的是终止响应的重新传输.

17.1.1.2 形式描述

INVITE 客户端事务的状态机如图 5 所示. 当 TU 用 INVITE request 发起新的客户端事务时, 必须进入初始状态 "Calling". 客户端事务必须将该请求传递给传输层发送 (见 Section 18). 如果使用不可靠传输, 客户端事务必须以 T1 的值启动 Timer A. 如果使用可靠传输, 客户端事务 SHOULD NOT 启动 Timer A (Timer A 控制请求重传). 对于任何传输, 客户端事务都必须以 64*T1 秒的值启动 Timer B (Timer B 控制事务超时).

当触发计时器A时,客户端事务必须通过将请求传递到传输层来重新传输请求,并且必须使用2*T1的值重置计时器.重传的形式化定义

在事务层的上下文中,获取先前发送到传输层的消息并再次将其传递到传输层.

当计时器A在2*T1秒后触发时,必须再次重新传输请求(假设客户端事务仍处于此状态).此过程必须继续,以便在每次传输后以双倍的间隔重新传输请求.这些重传只能在客户端事务处于"调用"状态时进行.

T1的默认值为500毫秒.T1是客户机和服务器事务之间RTT的估计值.元件可能(尽管不建议)在不允许一般互联网连接的封闭专用网络中使用较小的T1值.T1可以选择更大,如果事先知道(例如在高延迟访问链路上)RTT更大,则建议选择更大的T1.无论T1的值是什么,都必须使用本节中描述的重传指数退避.

如果当计时器B触发时,客户端事务仍处于"调用"状态,则客户端事务应通知TU已发生超时.客户端事务不能生成ACK.64*T1的值等于在传输不可靠的情况下发送七个请求所需的时间量.

如果客户机事务在"调用"状态下收到临时响应,它将转换到"继续"状态.在"继续"状态下,客户端事务不应再重新传输请求.此外,临时响应必须传递给TU.任何进一步的临时响应必须在"继续"状态下传递给TU.

当处于"呼叫"或"继续"状态时,收到状态代码为300-699的响应必须导致客户端事务转换为"已完成".客户端事务必须将接收到的响应传递给TU,并且客户端事务必须生成ACK请求,即使传输是可靠的(第17.1.1.3节给出了从响应构造ACK的指南),然后将ACK传递给传输层进行传输.ACK必须发送到原始请求发送到的相同地址,端口和传输.客户端事务应在进入"完成"状态时启动计时器D,对于不可靠的传输,其值至少为32秒,对于可靠的传输,其值为零秒.计时器D反映了当使用不可靠的传输时,服务器事务可以保持在"完成"状态的时间量.这等于INVITE服务器事务中的计时器H,其

默认值为64*T1.但是,客户机事务不知道服务器事务使用的T1的值,因此使用绝对最小值32s,而不是基于T1的计时器D.

在"完成"状态下接收到的最终响应的任何重传必须导致ACK重新传递到传输层进行重传,但新收到的响应不得传递给TU.响应的重新传输定义为根据第17.1.3节的规则匹配同一客户机事务的任何响应.

                           |INVITE from TU
Timer A fires |INVITE sent
Reset A, V Timer B fires
INVITE sent +-----------+ or Transport Err.
+---------| |---------------+inform TU
| | Calling | |
+-------->| |-------------->|
+-----------+ 2xx |
| | 2xx to TU |
| |1xx |
300-699 +---------------+ |1xx to TU |

ACK sent | | | resp. to TU | 1xx V | | 1xx to TU -----------+ | | +---------| | | | | |Proceeding |-------------->| | +-------->| | 2xx | | +-----------+ 2xx to TU | | 300-699 | | | ACK sent, | | | resp. to TU| | | | | NOTE: | 300-699 V | | ACK sent +-----------+Transport Err. | transitions | +---------| |Inform TU | labeled with | | | Completed |-------------->| the event | +-------->| | | over the action | +-----------+ | to take | ^ | | | | | Timer D fires | +--------------+ | - | | | V | +-----------+ | | | | | Terminated|<--------------+ | | +-----------+

             图5:INVITE客户端事务

如果在客户端事务处于"完成"状态时触发计时器D,则客户端事务必须移动到终止状态.

当处于"调用"或"继续"状态时,接收2xx响应必须导致客户端事务进入"终止"状态,并且响应必须传递给TU.此响应的处理取决于TU是否是代理

核心或UAC核心.UAC核心将处理该响应的ACK生成,而代理核心将始终向上游转发200(OK).代理和UAC之间对200(OK)的不同处理是在事务层中不进行处理的原因.

客户机事务必须在进入"终止"状态时立即销毁.这实际上是保证正确操作所必需的.原因是对INVITE的2xx响应处理不同;每个都由代理转发,UAC中的ACK处理是不同的.因此,每个2xx都需要传递给代理核心(以便转发)和UAC核心(以便ACK).不进行事务层处理.每当传输接收到响应时,如果传输层未发现匹配的客户端事务(使用第17.1.3节的规则),则响应将直接传递给核心.由于匹配的客户端事务被第一个2xx销毁,因此后续的2xx将找不到匹配,因此将被传递到核心.

17.1.1.3 ACK请求的构造

本节指定在客户端事务中发送的ACK请求的构造.生成2xxACK的UAC核心必须遵循第13节中描述的规则.

客户端事务构造的ACK请求必须包含Call-ID,From和Request-URI的值,这些值等于客户端事务传递给传输的请求中的头字段的值(称为"原始请求").ACK中的To header字段必须等于待ACK响应中的To header字段,因此通常通过添加tag参数而与原始请求中的To header字段不同.ACK必须包含单个Via 头字段,并且该字段必须等于原始请求的最上方 Via 头字段.ACK中的CSeq头字段必须包含与原始请求中相同的序列号值,但方法参数必须等于"ACK".

如果响应被ACK的INVITE请求具有路由头字段,则这些头字段必须出现在ACK中.这是为了确保ACK可以通过任何下游无状态代理正确路由.

尽管任何请求都可能包含正文,但ACK中的正文是特殊的,因为如果正文未被理解,则无法拒绝该请求.因此,不建议将非2xx的主体放置在ACK中,但如果这样做,主体类型将限制为出现在INVITE中的任何主体,假设对INVITE的响应不是415.如果是,则ACK中的主体可以是415中的Accept头字段中列出的任何类型.

例如,考虑以下请求:

INVITE sip:[email protected] SIP/2.0 Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKkjshdyff To: Bob <sip:[email protected]> From: Alice <sip:[email protected]>;tag=88sja8x Max-Forwards: 70 Call-ID: 987asjd97y7atg CSeq: 986759 INVITE

针对该请求的非2xx最终响应的ACK请求如下所示:

ACK sip:[email protected] SIP/2.0 Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKkjshdyff To: Bob <sip:[email protected]>;tag=99sa0xk From: Alice <sip:[email protected]>;tag=88sja8x Max-Forwards: 70 Call-ID: 987asjd97y7atg CSeq: 986759 ACK

17.1.2 非INVITE客户端事务

17.1.2.1 非INVITE事务概述

非INVITE事务不使用ACK.它们是简单的请求-响应交互.对于不可靠的传输,请求以从T1开始并加倍直到到达T2的间隔重新传输.如果接收到临时响应,则对于不可靠的传输继续进行重传,但间隔为T2.服务器事务仅在收到请求的重新传输时才重新传输它发送的最后一个响应,该响应可以是临时响应或最终响应.这就是为什么即使在临时响应之后请求重传仍需要继续的原因;他们将确保可靠地交付最终响应.

与INVITE事务不同,非INVITE事务对2xx响应没有特殊处理.结果是,只有一个对非INVITE的2xx响应被发送到UAC.

17.1.2.2 形式描述

非INVITE客户端事务的状态机如图6所示.它与INVITE的状态机非常相似.

当TU使用请求启动新的客户端事务时,将进入"尝试"状态.当进入此状态时,客户端事务应将计时器F设置为在64T1秒内启动.请求必须传递到传输层进行传输.如果正在使用不可靠的传输,则客户端事务必须将计时器E设置为在T1秒内启动.如果计时器E在仍处于该状态时触发,则计时器将重置,但这次的值为MIN(2T1,T2).当计时器再次启动时,将重置为分钟(4*T1,T2).此过程继续进行,以使重传以指数增长的间隔发生,该间隔以T2为上限.T2的默认值是4s,它表示非INVITE服务器事务在未立即响应请求时响应请求所需的时间.对于T1和T2的默认值,这将导致500毫秒,1秒,2秒,4秒,4秒,4秒等间隔.

如果在客户端事务仍处于"尝试"状态时触发计时器F,则客户端事务应通知TU超时,然后进入"终止"状态.如果在"尝试"状态下收到临时响应,则必须将响应传递给TU,然后客户端事务应移动到"继续"状态.如果在"尝试"状态下收到最终响应(状态代码200-699),则必须将响应传递给TU,并且客户端事务必须转换为"完成"状态.

如果计时器E在"继续"状态下触发,则必须将请求传递到传输层进行重新传输,并且必须使用T2秒的值重置计时器E.如果计时器F在"继续"状态下触发,则必须通知TU超时,并且客户端事务必须转换到终止状态.如果在"继续"状态下收到最终响应(状态代码200-699),则必须将响应传递给TU,并且客户端事务必须转换为"完成"状态.

一旦客户机事务进入"完成"状态,它必须将计时器K设置为在T4秒内启动(对于不可靠的传输),并在零秒内启动(对于可靠的传输)."已完成"状态的存在是为了缓冲可能接收到的任何额外的响应重新传输(这就是为什么客户端事务只保留一段时间)

不可靠的运输).T4表示网络清除客户端和服务器事务之间的消息所需的时间.T4的默认值为5s.使用第17.1.3节规定的规则,当响应与同一事务匹配时,即为重新传输.如果计时器K在此状态下触发,则客户端事务必须转换为"已终止"状态.

一旦事务处于终止状态,必须立即销毁它.

17.1.3 匹配对客户事务的响应

当客户机中的传输层接收到响应时,它必须确定哪个客户机事务将处理该响应,以便进行第17.1.1和17.1.2节的处理.最上方 Via header字段中的分支参数用于此目的.响应在两种情况下匹配客户端事务:

  1. 如果响应的最上方 Via header字段中的分支参数值与创建事务的请求的最上方 Via header字段中的分支参数值相同.

2. 如果CSeq头字段中的方法参数与创建事务的请求的方法匹配.该方法是必需的,因为CANCEL request构成不同的事务,但共享相同的分支参数值.

如果通过多播发送请求,则可能会从不同的服务器生成多个响应.这些响应在最上面的过孔中都具有相同的分支参数,但在To标记中有所不同.将使用根据上述规则收到的第一个响应,其他响应将被视为重传.这不是一个错误;多播SIP只提供了一种基本的"单跳发现式"服务,仅限于处理单个响应.详见第18.1.1节.

17.1.4 处理传输错误

                               |Request from TU
|send request
Timer E V
send request +-----------+
+---------| |-------------------+
| | Trying | Timer F |
+-------->| | or Transport Err.|
+-----------+ inform TU |
200-699 | | |
resp. to TU | |1xx |
+---------------+ |resp. to TU |
| | |
| Timer E V Timer F |
| send req +-----------+ or Transport Err. |
| +---------| | inform TU |
| | |Proceeding |------------------>|
| +-------->| |-----+ |
| +-----------+ |1xx |
| | ^ |resp to TU |
| 200-699 | +--------+ |
| resp. to TU | |
| | |
| V |
| +-----------+ |
| | | |
| | Completed | |
| | | |
| +-----------+ |
| ^ | |
| | | Timer K |
+--------------+ | - |
| |
V |
NOTE: +-----------+ |
| | |
transitions | Terminated|\<------------------+
labeled with | |
the event +-----------+
over the action
to take

图6:非INVITE客户端事务

当客户端事务向要发送的传输层发送请求时,如果传输层指示失败,则遵循以下过程.

客户端事务应通知TU发生传输故障,并且客户端事务应直接转换到"终止"状态.TU将处理[4]中描述的故障切换机制.

17.2 服务器事务

服务器事务负责向TU发送请求并可靠地传输响应.它通过状态机实现这一点.服务器事务在收到请求时由核心创建,并且需要对该请求进行事务处理(情况并非总是如此).

与客户端事务一样,状态机取决于收到的请求是否为INVITE请求.

17.2.1 INVITE服务器事务

INVITE服务器事务的状态图如图7所示.

当为请求构造服务器事务时,它将进入"继续"状态.服务器事务必须生成100(尝试)响应,除非它知道TU将在200毫秒内生成临时或最终响应,在这种情况下,它可能会生成100(尝试)响应.为了避免网络拥塞,需要这个临时响应来快速终止请求重传.100(Trying)响应是根据第8.2.6节中的程序构造的,除了在响应的to头字段中插入标记(当请求中不存在标记时)从5月降级为不应.请求必须传递给TU.

TU将任意数量的临时响应传递给服务器事务.只要服务器事务处于"继续"状态,这些事务中的每一个都必须传递到传输层进行传输.事务层不会可靠地发送它们(它们不会被事务层重新传输),也不会导致服务器事务状态的更改.如果在"继续"状态下接收到请求重传,则必须将从TU接收到的最新临时响应传递给传输层进行重传.根据第17.2.3节的规则,如果请求与相同的服务器事务匹配,则该请求为重传.

如果在"继续"状态下,TU将2xx响应传递给服务器事务,则服务器事务必须将该响应传递给传输层进行传输.事实并非如此

由服务器事务重新传输;2xx响应的重新传输由TU处理.然后,服务器事务必须转换到"终止"状态.

在"继续"状态下,如果TU将状态代码为300到699的响应传递给服务器事务,则响应必须传递给传输层进行传输,并且状态机必须进入"完成"状态.对于不可靠传输,定时器G设置为在T1秒内启动,而对于可靠传输,定时器G未设置为启动.

  这与RFC 2543有所不同,RFC 2543中的响应总是被重新传输,甚至通过可靠的传输.

当进入"完成"状态时,必须将所有传输的计时器H设置为在64T1秒内启动.计时器H确定服务器事务何时放弃重新传输响应.其值被选择为等于计时器B,即客户端事务将继续重试发送请求的时间量.如果定时器G触发,响应将再次传递到传输层进行重传,并且定时器G将在分钟(2T1,T2)秒内设置为触发.从那时起,当定时器G触发时,响应再次传递给传输,并使用双倍的值重置定时器G,除非该值超过T2,否则在这种情况下,将使用T2值重置定时器G.这与非INVITE客户端事务处于"尝试"状态的请求的重新传输行为相同.此外,当处于"完成"状态时,如果接收到请求重传,则服务器应将响应传递给传输以进行重传.

如果在服务器事务处于"已完成"状态时收到ACK,则服务器事务必须转换为"已ACK"状态.由于在此状态下忽略计时器G,因此响应的任何重新传输都将停止.

如果计时器H在"完成"状态下触发,则表示从未收到ACK.在这种情况下,服务器事务必须转换为"已终止"状态,并且必须向TU指示已发生事务失败.

                           |INVITE
|pass INV to TU
INVITE V send 100 if TU won't in 200ms
send response+-----------+
+--------| |--------+101-199 from TU
| | Proceeding| |send response
+------->| |\<-------+
| | Transport Err.
| | Inform TU
| |--------------->+
+-----------+ |
300-699 from TU | |2xx from TU |
send response | |send response |
| +------------------>+
| |
INVITE V Timer G fires |
send response+-----------+ send response |
+--------| |--------+ |
| | Completed | | |
+------->| |\<-------+ |
+-----------+ |
| | |
ACK | | |
- | +------------------>+
| Timer H fires |
V or Transport Err.|
+-----------+ Inform TU |
| | |
| Confirmed | |
| | |
+-----------+ |
| |
|Timer I fires |
|- |
| |
V |
+-----------+ |
| | |
| Terminated|\<---------------+
| |
+-----------+

图7:INVITE服务器事务

"ACK"状态的目的是吸收因重新传输最终响应而触发的任何额外ACK消息.当进入该状态时,计时器I设置为在T4秒内启动(对于不可靠的传输),在0秒内启动(对于可靠的传输).一旦计时器I启动,服务器必须转换到"终止"状态.

一旦事务处于"终止"状态,必须立即销毁.与客户端事务一样,这是确保对INVITE的2xx响应的可靠性所必需的.

17.2.2 非INVITE服务器事务

非INVITE服务器事务的状态机如图8所示.

状态机在"尝试"状态下初始化,并在初始化时传递除INVITE或ACK之外的请求.此请求被传递给TU.一旦处于"尝试"状态,任何进一步的请求重传都将被丢弃.使用第17.2.3节中指定的规则,如果请求与同一服务器事务匹配,则该请求为重传.

在"尝试"状态下,如果TU向服务器事务传递临时响应,则服务器事务必须进入"继续"状态.响应必须传递到传输层进行传输.当处于"继续"状态时从TU接收的任何进一步的临时响应必须传递到传输层以进行传输.如果在"继续"状态下接收到请求的重新传输,则最近发送的临时响应必须传递给传输层进行重新传输.如果TU在"继续"状态下将最终响应(状态代码200-699)传递给服务器,则事务必须进入"完成"状态,并且响应必须传递给传输层进行传输.

当服务器事务进入"完成"状态时,对于不可靠的传输,它必须将计时器J设置为在64*T1秒内启动,对于可靠的传输,它必须设置为零秒.在"完成"状态下,服务器事务必须将最终响应传递给传输层,以便在收到请求的重传时进行重传.TU传递给服务器事务的任何其他最终响应必须在处于"完成"状态时丢弃.服务器事务将保持此状态,直到计时器J触发,此时它必须转换到"终止"状态.

服务器事务进入"终止"状态时必须立即销毁.

17.2.3 将请求匹配到服务器事务

当服务器从网络接收到请求时,必须将其与现有事务匹配.这是通过以下方式实现的.

将检查请求的最顶端Via 头字段中的分支参数.如果存在并以神奇cookie"z9hG4bK"开头,则请求是由符合此规范的客户端事务生成的.因此,分支参数在该客户端发送的所有事务中都是唯一的.在以下情况下,请求与事务匹配:

  1. 请求中的branch参数等于创建事务的请求的最上方 Via header字段中的参数,并且

2. 请求顶部通孔中的sent-by值等于创建事务的请求中的值,并且

3. 请求的方法与创建事务的方法匹配,ACK除外,其中创建事务的请求的方法为INVITE.

此匹配规则同样适用于INVITE和非INVITE事务.

  sent-by值用作匹配过程的一部分,因为可能会意外或恶意复制来自不同客户端的分支参数.

如果最上方 Via header字段中的branch参数不存在,或者不包含magic cookie,则使用以下过程.它们的存在是为了处理与RFC2543兼容实现的向后兼容性.

如果Request-URI,To标记,From标记,Call-ID,CSeq和最上方 Via 头字段与创建事务的INVITE请求的URI,To标记,From标记,Call-ID,CSeq和最上方 Via 头字段匹配,则INVITE请求与事务匹配.在这种情况下,INVITE是创建事务的原始INVITE的重新传输.如果Request-URI,From标记,Call-ID,CSeq编号(不是方法)和最上方 Via 头字段与创建事务的INVITE请求的URI匹配,并且ACK的To标记与服务器事务发送的响应的To标记匹配,则ACK请求与事务匹配.根据为每个头字段定义的匹配规则进行匹配.在ACK匹配过程中,将标记包含在To header字段中有助于消除2xx的ACK与其他响应的ACK之间的歧义

在一个代理上,该代理可能转发了两个响应(在异常情况下可能会发生这种情况.特别是,当一个代理分叉一个请求,然后崩溃时,响应可能会被传递到另一个代理,而另一个代理可能会向上游转发多个响应).与先前ACK匹配的INVITE事务匹配的ACK请求被视为该先前ACK的重传.

                              |Request received
|pass to TU
V
+-----------+
| |
| Trying |-------------+
| | |
+-----------+ |200-699 from TU
| |send response
|1xx from TU |
|send response |
| |
Request V 1xx from TU |
send response+-----------+send response|
+--------| |--------+ |
| | Proceeding| | |
+------->| |\<-------+ |
+\<--------------| | |
|Trnsprt Err +-----------+ |
|Inform TU | |
| | |
| |200-699 from TU |
| |send response |
| Request V |
| send response+-----------+ |
| +--------| | |
| | | Completed |\<------------+
| +------->| |
+\<--------------| |
|Trnsprt Err +-----------+
|Inform TU |
| |Timer J fires
| |-
| |
| V
| +-----------+
| | |
+-------------->| Terminated|
| |
+-----------+

图8:非INVITE服务器事务

对于所有其他请求方法,如果Request-URI,to标记,From标记,Call-ID,CSeq(包括该方法)和最上方 Via 头字段与创建事务的请求的URI,to标记,From标记,Call-ID,CSeq和最上方 Via 头字段匹配,则请求与事务匹配.在匹配的基础上进行匹配

为每个头字段定义的规则.当非INVITE请求与现有事务匹配时,是对创建该事务的请求的重新传输.

因为匹配规则包括Request-URI,所以服务器无法匹配对事务的响应.当TU将响应传递给服务器事务时,它必须将其传递给响应所针对的特定服务器事务.

17.2.4 处理传输错误

当服务器事务向要发送的传输层发送响应时,如果传输层指示失败,则遵循以下过程.

首先,遵循[4]中的过程,尝试将响应传递给备份.如果这些都失败了,根据[4]中的失败定义,服务器事务应通知TU发生了故障,并应转换到终止状态.