SIP表示会话初始化协议(Session Initiation Protocol)。该协议是一个应用层控制协议,由IEEE设计和开发。设计的时候考虑到了协议的实现容易、良好的规模性和灵活性。
该规范由几个RFC组成,其中最重要的一个是RFC3261,为规范的核心内容。该协议用来创建、修改和终止与一个或多个参与者之间的会话。利用会话,我们理解为一组相互通信的发送者和接收者及在通信过程中保存在这些发送者和接收者的状态。会话的例子包括互联网电话呼叫、多媒体的分发、多媒体会议、分布式计算机游戏等。
SIP不仅是一个通信设备需要的协议,也不是一个通用的协议。SIP的目的仅在于使得通信成为可能。通信本身必须由其他方式来实现(可能是其他的协议)。经常与SIP一同使用的其他两种协议是RTP和SDP。RTP协议用来承载实时的多媒体数据,包括音频、视频和文本。这个协议使得对数据编码和打包,并在Internet上传输这些包成为可能。另外一个重要的协议是SDP,会话描述协议(Session Description Protocol),它被用来对会话参与者的能力进行描述和编码。这样的描述然后被用于会话特征的协商,以便所有的设备能够参与,例如,对媒体编码的协商,便于所有的参与者能够对媒体解码;传输协议的协商,等等。
SIP被设计用来遵从Internet的工作模式。它是一个面向端到端的信令协议,这意味着所有的逻辑都存储在端设备上(除了SIP消息的路由);状态也只存储在端设备上。系统里没有单点失效,使用这种方式设计的网络有非常好的规模扩充性。为这种分布式和规模扩充性所付出的代价是消息的高开销,因为消息必须在端到端之间发送。
值得一提的是,SIP的端到端的概念对于常规的PSTN来讲,是一个巨大的改变。在PSTN中,所有的状态和逻辑都保存在网络里,而端设备(电话)是原始的“笨”设备。SIP的目的是提供与传统PSTN相同的功能,但端到端的设计使得SIP网络有更大的威力,而且更加开放,便于实现一些新的服务,而这些服务在传统的PSTN上几乎是不可能的。
SIP是基于HTTP协议的。HTTP协议继承了RFC822的消息头的格式。HTTP可能是在Internet上最成功和广泛使用的协议。SIP试图结合两者的优点。事实上,HTTP也可以被分类为信令协议,因为用户代理使用这个协议告诉HTTP服务器起对那个文件感兴趣。SIP用来承载会话参数的说明,这个说明用SDP来编码到一个文档里。这两个协议,HTTP和SIP,都继承了RFC822的消息头的编码。在过去的几年里,编码被证明是很强健和灵活的。
2.1.1 SIP URI
SIP实体使用SIP URI (Uniform Resource Identifier)来标识。SIP URI的形式为:username@domain,或者sip:joe@company.com。SIP URI 包括用户名和域名两部分,使用@ (at)来分隔。
SIP URI类似于e-mail地址,因此可以使用相同的URI用于e-mail和SIP通信。这样的URI很容易记忆。
SIP网络的最基本的配置可以只有两个元素,两个用户代理,两者之间直接互传消息;但是典型的SIP网络会包含多种类型的SIP消息。基本的SIP元素是用户代理(UA),代理(Proxy)、注册服务器(registrar)和重定向服务器(redirect server)。本节会简要介绍这些元素。要注意的是,这些元素是一些逻辑实体,例如,为了加快处理的速度,常常会把他们在物理上放在一起,这取决于具体的实现和配置。
2.2.1 用户代理(UA)
使用SIP协议来寻找对方和协商会话特点的Internet端点被称为用户代理。用户代理通常(不是必须)以应用的形式存在于用户的计算机上,这是目前最广泛使用的方式,不过用户代理也可以是蜂窝电话、PSTN网关、PDA、语音自动应答(IVR)系统等。用户代理也常常被称为用户代理服务器(UAS)和用户代理客户(UAC)。UAS和UAC是逻辑实体,每个用户代理都包括UAS和UAC。UAC在用户代理中负责发送请求和接收响应,而UAS负责接收请求和发送响应。
由于用户代理包括UAS和UAC,所以其行为就像UAS或UAC。例如,主叫方用户代理在发送INVITE请求和响应对方的时候是UAC,被叫方的用户代理在接收INVITE请求和发送响应给对方的时候是UAS。
但是当被叫方决定发送BYE和中止请求的时候,情况就不一样了。在这种情况下,被叫方的用户代理(发送BYE)的作为UAC,而主叫方的用户代理作为UAS。
图2.11 UAC和UAS
图2.11中有三个用户代理和一个静态的分支代理服务器。每个用户代理都包括UAC和UAS,代理部分负责接收来自主叫方的INVITE,实际上也就是UAS。在做静态请求转发时,代理创建两个UAC,每个UAC负责一个分支。
在这个例子中,被叫方B拾起听筒,而之后,如果要断开呼叫,就发出一个BYE消息。此时,原先用作UAS的代理现在变作UAC,原先用作UAC的代理现在变作UAS。
2.2.2 代理服务器
SIP允许建立一种被称为代理服务器的网络主机的基本设施。用户代理可以给代理服务器发送消息。代理服务器在SIP网络中是非常重要的一种实体,负责按照被请求者当前的位置完成路由、认证、记账和其他重要的功能。代理服务器最重要的任务是把会话请求路由到‘接近’到被叫方。一般情况下,会话请求会遍历一组代理服务器,直到找到知道被叫方实际位置的代理服务器。这个代理服务器会直接转发会话请求给被叫方,然后被叫方接受或拒绝该会话请求。
SIP代理服务器分为两种类型:无状态代理服务器和有无状态代理服务器。
2.2.2.1 无状态服务器
对消息作简单的转发,彼此之间没有依赖关系。尽管消息通常安排在交易内部(见2.2.2.4节),无状态代理服务器并不关心交易。
无状态代理服务器简单,比状态代理服务器速度快,可以作为简单的负载均衡器、消息翻译器和路由器来使用。无状态代理服务器的缺点是不能吸收重传消息,或完成高级路由,例如分支和递归遍历。
2.2.2.2 状态服务器
状态代理服务器相对复杂,它在接收到请求时建立一个状态并保持该状态直到交易完成。某些交易,特别是那些由INVITE创建的,能够持续很长时间(直到被叫方拾起听筒或拒绝该呼叫)。由于状态代理服务器在交易存续期间必须维持状态,所以性能受到限制。将SIP消息与交易关联能够给状态代理服务器带来某些有用的特性。状态代理服务器能够完成分支,这意味着在接收到一个消息,可以发送两个或更多的消息出去。
状态代理服务器可以吸收重传消息,因为如果它已经接收到这个消息,它就可以从状态中知道(无状态代理服务器没有保留状态,因此无法检查)。
状态代理服务器可以使用更复杂的方法来查找用户,例如,当用户没有接听电话,可以尝试拨他的办公室电话,或者将电话重定向到用户的移动电话上。无状态代理服务器无法做到这一点,因为它无法知道到办公室电话的交易如何结束。
现在多数的SIP代理服务器都是有状态的,它们的配置通常都很复杂,要完成记账、分支和一些NAT穿透,这些功能都要求使用状态代理服务器。
2.2.2.3 代理服务器的使用
假定有两个公司, A和B,每个公司都有自己的代理服务器,图2.12说明了来自公司A中员工Joe的会话请求如何到达公司B的员工Bob。
图 2.12 会话请求
用户Joe使用地址sip:bob@b.com来呼叫Bob。Joe的用户代理自己不知道如何路由该请求,但是被配置成把所有向外发送的消息发送到公司的代理服务器proxy.a.com上。该代理服务器计算出被叫用户sip:bob@b.com在其他公司,因此查询B公司的代理服务器,并将请求发送到那里。B公司的代理服务器可以预先配置在proxy.a.com,或者该代理使用DNS SRV记录来找到B的代理服务器。请求到达proxy.b.com,它知道Bob目前在公司,可以通过电话找到,并且他的IP地址为1.2.3.4,于是把请求发送到那里。
2.2.3 注册服务器
前面已经提到,在proxy.b.com的SIP代理服务器知道Bob的当前位置,但是没有说明该代理服务器如何学习到用户的当前位置。Bob的用户代理(SIP电话)必须注册到注册服务器上。注册服务器是一个特殊的SIP实体,其接收来自用户的注册请求,抽取出用户当前位置的信息(IP地址、端口和用户名)并把这些信息保存在位置数据库中。位置数据库的作用是把sip:bob@b.com映射到类似sip:bob@1.2.3.4:5060的地址上。B公司的代理服务器使用位置数据库。当代理服务器接收到sip:bob@b.com对的请求时,它在位置数据库中搜索,发现sip:bob@1.2.3.4:5060,并请将邀请发送到那里。
注册服务器通常也是一个逻辑实体,由于和代理服务器的紧密关系,两者常常处于同一个物理位置。
图2.13是一个典型的SIP注册服务器。REGISTER消息将发送给注册服务器,其中包括记录sip:jan@iptel.org的地址和联系地址sip:jan@1.2.3.4:5060,其中的1.2.3.4是话机的IP地址。注册服务器把这些信息抽取出来,将其存储到位置数据库中,如果一切顺利,注册服务器给电话发出一个200 OK的响应,注册过程的处理也相应结束。
图 2.13 注册服务器
每个注册都有限定的生命期。联系头域中expires参数,或者expires头域决定了注册在多长时间内是有效的。用户代理必须在注册生命期内刷新注册,否则注册将会到期,用户将不能使用服务(不可达)。
2.2.4 重定向服务器
接收到请求,然后发回的应答中包括指定的用户的当前位置列表的实体,称为重定向服务器。重定向服务器接收请求,在位置数据库(由注册服务器建立)中查找该请求的接收者,然后创建一个用户当前位置列表,并在响应(使用SIP 3xx重定向响应类)中将这个列表发送给请求的发起者。请求的发起者从响应中抽取被叫地的列表,然后直接给他们发出另外的请求。图2.14是一个典型的重定向例子。
图2.14 SIP重定向
使用SIP (经常被称为信令)的通信由一系列消息组成。消息可以由网络独立传输,通常由单独的UDP数据报来传输。每个消息都包括一个‘首行’,一个消息头,一个消息体。首行用来标识消息的类型。消息分为两种类型:请求和响应。请求用来启动某个动作,或者向请求的接收者发出通知。响应用来确认请求已被接收和处理,并包括处理的状态。
下面的例子是典型的SIP请求:
INVITE sip:7170@iptel.org SIP/2.0
Via: SIP/2.0/UDP 195.37.77.100:5040;rport
Max-Forwards: 10
From: “jiri” <sip:jiri@iptel.org>;tag=76ff7a07-c091-4192-84a0-
d56e91fe104f
To: <sip:jiri@bat.iptel.org>
Call-ID: d10815e0-bf17-4afa-8412-d9130a793d96@213.20.128.35
CSeq: 2 INVITE
Contact: <sip:213.20.128.35:9315>
User-Agent: Windows RTC/1.0
Proxy-Authorisation: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri@bat.iptel.org",
nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c",
response="53fe98db10e1074
b03b3e06438bda70f"
Content-Type: application/sdp
Content-Length: 451
v=0
o=jku2 0 0 IN IP4 213.20.128.35
s=session
c=IN IP4 213.20.128.35
b=CT:1000
t=0 0
m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
a=rtpmap:97 red/8000
a=rtpmap:111 SIREN/16000
a=fmtp:111 bitrate=16000
a=rtpmap:112 G7221/16000
a=fmtp:112 bitrate=24000
a=rtpmap:6 DVI4/16000
a=rtpmap:0 PCMU/8000
a=rtpmap:4 G723/8000
a=rtpmap: 3 GSM/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
首行表明这是一个用来建立会话的INVITE消息,其中的URI,sip:7170@iptel.org,被称为被叫请求URI,包含消息下一跳的URI,在这个例子中,就是主机iptel.org.。
一个SIP请求包含一个或多个Via头域,该域用来记录请求的路径,而后会被用来对SIP消息进行精确的路由。INVITE消息仅包括Via头域,它是由发送请求的用户代理创建的。根据Via头域,我们知道用户代理运行在ip地址为195.37.77.100的主机上,端口为5060。
From和To头域用于标志邀请的发起者(主叫)和接收者(被叫),类似于SMTP中消息的发送者和接收者。
From头域包含一个tag参数,用作对话标识,我们将在2.2.2.5节中描述。
Call-ID头域是一个对话标识,其目的是标识消息属于同一个呼叫。这样的消息具有相同的Call-ID。
Cseq用来维持请求的顺序。由于请求可能在不可靠的链路上传输,因此消息的到达先后顺序会有所不同,所以在消息中必须包含序号,以便接受者可以识别重传的消息和顺序不正确的请求。
Contact头域包括IP地址和发送者用来侦听被叫方发送的请求的端口号。
其他的域相对不重要,这里不再叙述。
Message与消息体之间使用空行来分隔。INVITE请求的消息体包括发送者可接受的媒体类型的说明,并在SDP中编码。
2.3.1 SIP请求
前面已经描述了INVITE请求。这个请求用来请求被叫方进入一个会话。
其他几个重要请求是:
- ACK
这个消息是对接收到INVITE消息的最后应答。会话的建立使用了3次的握手,这是由于邀请的非对称本质所决定的。被叫方接受或者拒绝呼叫之前,需要花费一段时间,因为被叫方的代理要定时重传正式的回应,直到其接收到一个ACK 消息(表示主叫方仍在,并且准备通话)。
- BYE
BYE用于撤销多媒体会话。任何一方希望撤销会话的话,就向另一方发出BYE消息。
- CANCEL
CANCEL用于撤销一个还没有完全建立的会话,在被叫方还没有用最终的回应来回答之前,若主叫方打算取消这个呼叫时使用(例如,被叫方长时间没有回应)。
- REGISTER
REGISTER消息的目的是让注册服务器(registrar)知道用户当前的位置(地址)。有关用户可以通达的当前IP地址和端口的信息都用REGISTER 消息来承载。注册服务器抽取出这些信息,将其放入地点数据库。SIP代理服务器会利用该数据库把呼叫路由到用户那里。注册是有时间限制的,需要周期性的刷新。
上述请求通常没有消息体,因为在多数情况下不需要使用(但可能有),另外,还定义了许多其它请求类型,这里不对它们进行描述。
2.3.2 SIP响应
当用户代理或代理服务器接收到一个请求时,会发送一个响应。除了ACK请求之外,其他的请求都要有响应。
下面的例子是典型的SIP响应:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.1.30:5060;received=66.87.48.68
From: sip:sip2@iptel.org
To: sip:sip2@iptel.org;tag=794fe65c16edfdf45da4fc39a5d2867c.b713
Call-ID: 2443936363@192.168.1.30
CSeq: 63629 REGISTER
Contact: <sip:sip2@66.87.48.68:5060;transport=udp>;q=0.00;expires=120
Server: Sip EXpress router (0.8.11pre21xrc (i386/linux))
Content-Length: 0
Warning: 392 195.37.77.101:5060 "Noisy feedback tells:
pid=5110 req_src_ip=66.87.48.68 req_src_port=5060
in_uri=sip:iptel.org
out_uri=sip:iptel.org via_cnt==1"
除了首行之外,响应与请求类似。响应的首行包括协议版本(SIP/2.0)、回答代码和理论周期。回答代码是100到699之间的整数,用来标明响应的类型,响应分为6类:
-1xx 是临时响应,它告诉响应的接收者,已经收到与之相关的请求,但是还不知道处理的结果。临时响应只有在处理尚未完成时发送。一旦接收到临时响应,请求的发送者应该立即停止重传。
典型的例子是,代理服务器开始处理INVITE请求时,用代码100来响应;如果用户代理使用180来响应,表示被叫电话正在振铃。
-2xx 是确定的最终响应,使用200到299之间的数字作为代码。最终响应反映了与之相关的请求处理结果,并且会终止交易。最终响应表示请求已经成功处理并被接受,例如,当用户接受了会话邀请(INVITE请求),就发送一个200 OK的响应。
对于一个INVITE请求,UAC有可能会接收到几个200消息,这是因为代理服务器(见后面)能够将请求分支发送,从而到达几个UAS,每个UAS都接受邀请。在此种情况下,响应使用To头域中的tag参数来区分。每个响应都使用唯一的对话标识,用来代表对话。
- 3xx 响应用来重定向主叫方。重定向响应给出用户新位置的相关信息,或者主叫方能够用来满足该呼叫的其它服务的信息。重定向响应一般由代理服务器发出。当代理服务器收到请求,但是因为某些原因不想处理或不能够处理,它就会向主叫方发出重定向响应,并且把主叫方要尝试的另一个地点放在响应中,这个地点可以是另一个代理服务器,或者被叫方的当前位置(来自由注册服务器创建的位置数据库)。然后主叫方向新地点重新发出请求。3xx响应是最终的。
- 4xx 是否定的最终响应,4xx响应表示问题在另外一个方面,请求不能被处理是因为它包含不正确语法,或者服务器没有实现对此种请求的处理功能。
- 5xx 响应表示问题在服务器方,请求是有效的,但是服务器没有能够完成请求,客户端应该在稍后重新尝试该请求。
- 6xx 回答代码表示任何服务器都不能完成请求。这个响应通常由具有特定用户信息的服务其发出。当用户不想参与会话时,用户代理通常发出一个603 Decline响应。.
除了上述类别的响应,首行也包括理论周期,代码编号是要机器处理的,其并不是很好记忆,但是很容易扫描分析和被机器理解。理论周期包括描述处理结果的可读消息。用户代理应该附加一个原因说明给用户。对特定响应的请求利用CSeq头域来标识。除了顺序编号,这个域还包括对应于请求的方法,在前面的例子里,就是REGISTER 请求。
尽管SIP消息可以独立的在网络上传送,但通常被用户代理和某些类型的代理服务器安排成交易,因此,SIP可以说是一种交易类的协议。
交易是在网络元素之间交换的SIP消息序列。一个交易包括一个请求和所有对该请求的响应,其中包括0个或多个临时相应,以及一个或多个最终响应(记住:当代理服务器对INVITE请求分支时,对该请求可能会有多个响应。)
如果交易由INVITE发起,那么该交易也包括ACK,但只限于最终响应不是2xx的情况。如果最终响应是2xx,那么就不把ACK当作是交易的一部分。
我们可以看到,这是一种不对称的行为,ACK是否定的最终响应的一部分,但不是具有确定性响应的交易的组成部分,其原因是传递200 OK消息非常重要。当代理服务器分支请求时,不仅要建立会话,多个实体还要生成200 OK消息,并且这些消息还要传递给主叫的用户代理。于是用户代理负起责任,并重传200 OK,直到他们接收到ACK。注意只有对INVITE的响应才被重传。
具有交易概念的SIP实体被称为有状态的,这样的实体通常一个与交易关联的状态,在交易存续期间保存在内存中。当请求或响应到来时,有状态的实体试图把该请求(响应)与现有的交易关联起来。为了做到这点,它必须从消息中抽取唯一的交易标识,并将其与现有的交易中的标识比较。如果有这样的交易存在,那么其状态将会根据消息来更新。
在SIP RFC2543, 交易标识根据所有重要消息的头域(包括To、From、Request-URI和CSeq)hash得来,这很慢,并且复杂,在互操作性测试中,这往往是问题的根源。
但是在RFC3261,计算交易标识的方法完全改变了,取代了原先的对所有重要消息的头域进行hash的方法,现在的SIP消息中直接包括了交易标识,Via头域的分支参数直接包括了交易标识。这是一个巨大的简化,但是原先的实现依然保留着,以便保持向后兼容。
图2.15说明了两个用户代理对话期间,什么消息属于什么交易。
图2.15 SIP交易
我们已经说明了什么是交易,一种由INVITE和对其的响应组成;另一种由BYE和对其的响应组成(在会话断开时)。这两个交易是有某些关联的,同属一个对话。对话代表两个用户代理之间的点到点SIP关系。对话会持续一段时间,对于用户代理来讲对话是一个很重要的概念。对话有利于在SIP端点之间排出正确的消息路由和顺序。
对话使用Call-ID、From tag和To tag来标识。同一个对话的消息中的这些域的内容必须相同。我们已经说明CSeq头域用来对消息排序,事实上,它是在对话内部来对消息排序,在每一个对话内,发出的消息的序号必需单向增加,否则,对方会认为是一个错误或重传的请求。这意味着在一个对话内部,在一个方向上,只有一个交易是活动的,也可以说,对话是交易的序列。图2.16对图2.1进行了扩充,显示的是属于同一个对话中的消息。
图2.16 SIP对话
某些消息建立对话,而某些消息不建立。对话用来明确标明消息的关系,也会发出与对话之外的消息没有关联的消息。这很容易实现,因为用户代理不维持对话状态。例如,INVITE消息建立对话,它的后面会跟有BYE请求,用来断开INVITE建立的会话,这个BYE在由INVITE建立的会话内部发送。但是,如果用户代理发出MESSAGE请求,而这样的请求并不建立任何对话,期后面的消息(包括MESSAGE)都将独立发送,而与前面的消息无关。
2.5.1 对话方便路由
对话还用于在用户代理之间路由消息,简单叙述如下。
假定用户sip:bob@a.com要与用户sip:pete@b.com通话,他知道被叫方(sip:pete@b.com)的SIP地址,但是这个地址并没有说明用户当前的位置,也就是说,主叫方不知道向那个主机发出请求。因此,向代理服务器发出INVITE请求。
该请求将从一个代理服务器发到另一个代理服务器,直到有一个代理服务器知道被叫方当前的位置。这个过程称为路由。一旦请求到达被叫方,被叫方的用户代理产生一个响应,发送给主叫方。被叫方的用户代理还会把含有用户当前位置信息的联系信息头域包括在响应中,原始的请求也会包含在联系信息头域中,表示两个用户代理都知道彼此的当前位置。
由于两个用户代理都知道彼此的当前位置,因此不需要再向任何代理服务器发出请求,两者可以直接发送,这就是对话如何方便路由。
对话中的其余消息直接在用户代理之间传送,这是一个巨大的性能改进,因为代理服务器不用看到所有对话中的消息,他们仅用于建立对话的第一个请求。直接传送的消息具有较小的延迟,因为代理服务器通常都实现了很复杂的路由逻辑。图2.17中是一个包含在对话(BYE)中旁路代理服务器的消息的例子。
图 2.17 SIP的梯形示意
2.5.2 对话标识符
对话标识符由三部分组成:Call-Id、From tag和To tag,但是为什么这样创建对话,以及谁负责那个部分并不是很清晰。Call-ID被称为呼叫标识符,必须是唯一的。一个呼叫包括一个或者多个对话,当代理服务器分支请求时,多个用户代理可能会对一个请求产生回应。发送2xx响应的每一个用户代理都与主叫方建立一个单独的对话,所有这些对话都同属一个呼叫,并有相同的Call-ID。
From tag由主叫方产生,唯一的标识主叫方用户代理的对话。
To tag由被叫方产生,类似于From tag,用来唯一标识主叫方用户代理的对话。
这种分等级的对话是必需的,因为一个邀请(Invitation)可能产生多个对话,而主叫方必须能够区分他们。
本节给出几个典型的SIP使用场合。
2.6.1 注册
用户必须把自己注册到注册服务器上,这样起他的用户才能够找到自己。注册包括一个REGISTER消息,紧接着是注册服务器发出的200 OK(假设注册成功)。注册通常是要认证的,所以如果用户没有提供有效的信任证书,就会得到一个407回答。图2.18是一个注册的例子。
图2.18 REGISTER消息流
2.6.2 会话邀请
会话邀请包括一个发送给代理服务器的INVITE请求,代理服务器立即发送一个100 Trying回应来阻止请求的重传,并进一步转发请求。所有由被叫方产生的provisional响应都会立即发送给主叫方,请参考呼叫流程中的180 Ringing,当被叫方的电话振铃时会产生该响应。
一旦用户摘机,就会立即生成200 OK,由被叫方的用户代理重传,直到其从主叫方收到ACK,此时,会话就已经建立。
2.6.3 会话终止
会话终止通过在由INVITE请求建立的对话内发送BYE请求来实现。BYE消息直接从一个用户代理发到另一个用户代理,除非INVITE请求路径上的一个代理服务器用记录路由来明示它希望停留在该路径上(见2.2.2.6.4节)。
希望断开会话的一方发出BYE请求给会话的另一方,而另一方发送一个200 OK响应来确认这个BYE,然后会话终止。见图2.20中左边的流程。
图2.19 INVITE消息流
2.6.4 记录路由
在默认情况下,在对话内部发送的所有请求都是直接从一个用户代理到另一个用户代理。只有对话外的请求会遍历SIP代理服务器。这个方法使得SIP网络会具有更好的伸缩性,因为只有少量的SIP消息会到达代理服务器。
某些情况下,需要代理服务器停留在后续消息的路径上,如控制NAT的代理服务器,或计费代理服务器需要停留在BYE请求的路径上。
代理服务器用来通知用户代理它希望停留在后续消息的路径上的机制称为记录路由。这样的代理服务器会在SIP消息中插入一个Record-Route头域,其包含了代理服务器的地址。对话内发送的消息会遍历所有在SIP消息中插入Record-Route头域的代理服务器。
请求地接收者会接收到消息中的一组Record-Route头域,它必须在响应中镜像所有的Record-Route头域,因为请求的发起者也需要知道这些代理服务器。
图2.20 BYE 消息流(带有和不带有记录路由)
图2.20中左侧的消息流说明的是在消息中没有Record-Route头域的情况下,BYE请求(在由INVITE建立的对话内)直接发送给其他的用户代理。右侧的消息流说明的是当代理服务器把Record-Route头域放进消息的情况。
2.6.5 事件预订和通知
SIP规范已经扩展到支持允许事件预定。这样的事件包括:代理服务器的统计改变、存在的消息、会话改变等等。
这样的机制主要用于传递有关用户存在(愿意通信)的信息。图2.21显示的是基本的消息流。
图2.21 事件预定和通知
有意进行事件预定的用户代理发出一个SUBSCRIBE消息给SIP服务器。SUBSCRIBE消息建立一个对话,并会马上得到服务器发回的200 OK响应。此时,对话已经建立。然后,每次用户预定的事件发生时,服务器都会发送NOTIFY请求给用户。NOTIFY消息在由SUBSCRIBE建立的对话内发送。
注意:在图2.21中,不管是否有事件触发通知,都会发送第一个NOTIFY消息。
事件预定和注册一样,都有确定的生命期,因此必须周期性的更新。
2.6.6 即时消息
即时消息使用MESSAGE请求发送。MESSAGE请求不建立对话,因此它总是会遍历同一组代理服务器,这是发送即时消息的最简单方法。即时消息的文本在SIP请求的体内传输。
图 2.22 即时消息
在传统电话网络中,基础设施由大量的交换机组成,这些交换机彼此互连构成骨干网络,此外它们还与用户设备(PBX, 电话)连接。目前的内部网络采用的是数字通信,而到用户的链路可以是模拟的(PSTN)也可以是数字的(ISDN)。用户链路由呼叫信令(如拨号、补充服务等)和语音/数据来共享。在骨干网络中,在交换机之间为呼叫信令保留了专门(虚拟)的链路(实际上构成了专门的信令网络),而语音/数据在另外的链路上传输。7号信令系统(SS7),或者其变种用作交换机之间的呼叫信令协议,该协议用来在骨干网络中路由语音/数据通道,通过指令路由上的每一台交换机哪一个来话线路转接到哪一个去话线路,以及施加其他的处理功能(如语音压缩、到用户设备的带内信令检测等等)。语音/数据通道本身是简单的数据位管道,在每一台交换机上使用中继和线路标识。
图 2.23 MGCP的应用场景
几个电信运营商在考虑把类似的结构用在基于IP的骨干网上,这个主干网会逐渐取代交换网中的部分主干,如图3.7。IP路由器取代语音交换机来建造主干网络,利用IP路由,甚至MPLS,明确的支持QOS,可以在网络中的一个地方把语音或数据包传输到临一个地方。与语音交换机相反,这不需要为每个语音连接去配置每个路由器,只是需要在入口和出口把对方的地址配置进去,因此才可以知道把语音或数据送到那里去。在IP网络的边缘使用两种类型的网关来连接传统的电话网络:
信令网关,把SS7信令转换为基于IP的控制(可以使用H.323或SIP在IP包中承载SS7信令[SIGTRAN]);媒体网关,完成语音编码的转换。某些中心实体,或者几个协同的实体,共同构成骨干网络的智能核心,媒体网关控制器(Media Gateway Controller)。他们负责解释呼叫信令,决定如何路由呼叫,提供补充服务等。在决定了如何建立呼叫之后,他们通知处在边缘(出、入)的媒体网关如何传输语音包,以及把语音包传输到什么地方。媒体网关控制器在呼叫发生改变的时候,如请求补充服务等,也会重新配置网关。媒体网关能够监测到在媒体通道中的控制功能请求(比如,利用DTMF),并通知媒体网关控制器,后者会引发相应的动作。
媒体网关控制器和媒体网关之间的通信协议已经定义了几个。最初的版本有多个阵营开发,其中几个合并起来创立了媒体网关控制协议(MGCP),这是唯一一个专有协议成为报告性质的RFC(RFC 2705)。现在正在做出努力,使得剩下的两个阵营进行合作,并开发一个可以标准化的协议,这样就产生了ITU-T(Q.14)和IETF的工作组(MEGACO WG)。这个联合开发的协议被ITU-T称为H.248,在IETF中被称为MEGACO。
目前IETF正在讨论的一个特别的协议扩充是利用用户所拥有的IP电话机进行通信的定义,实现与媒体网关控制体系结构的无缝结合。这样的电话将会非常简单,当通化服务直接由网络基础设施提供时,它能够发送、接收事件,并对事件作出反应。.
现在,几乎所有提供VoIP产品的的厂商都使用其自己的VoIP协议。如Cisco的Skinny,Siemens的CorNet。这些协议都是由厂商发明,能够提供更多的专门的VoIP补充服务,以便为用户提供所有的传统PBX的功能。企业解决方案通常都采用了这些专有协议,对标准协议在基本的呼叫功能方面提供最低的支持。
给出这些协议的详细信息已经超出了本书的范围,而且也比较难以提供,应为这些协议都不是公开的。
RTP和RTCP是用于IP电话媒体流的传输协议,它们在RFC1889中定义。前者作为承载数据的协议并具有实时的特性,而后者用来监视服务的质量并传递正在进行的会话的相关信息。由RTP协议提供的服务包括:
标识被承载的信息(音频和视频编解码);
检查传递的数据包的顺序,必要时,对非正常的块重新排序;
传送编码器/解码器同步信息
监视信息传递
RTP协议使用下层的用户数据报协议(UDP)来管理两个实体之间的多个连接,以及检查数据的完整性(校验和)。重要的一点是RTP部提供任何方式来保证QoS,也不假定下层的按顺序传递数据包。
RTCP同样使用UDP来向所有的会话参与者周期的发送控制包。每个使用端口号N的RTP通道都有自己的RTCP协议通道,并且端口号为N+1。由RTCP协议提供的服务包括:
提供有关数据质量分布的反馈信息。反馈信息用来保持活动编解码控制
传送RTP源(CNAME)的连续标识符,视频数据使用
广播会话参与者的数量,以便调节RTP数据的传输速率
承载会话控制信息,用来标识会话的参与者
下面的两个小节描述RTP和RTCP头,以及两个协议所使用的各种数据包的类型。
图2.24是RTP头。前12个字节出现在所有的RTP数据包中;后面的字节,包括CSRC (Contributing SouRCe)标识符列表,只有在混合器交叉时才存在(混合器指接受两个以上的RTP流,将它们混合后再转发的系统)。
图2.24 RTP头
下面是头域的具体细节:
- 版本(V - 2位),RTP协议的版本;
- 填充位(P – 1位),如果设置为1,那么该数据包在数据域之后包含一个或更多的字节;
扩展位(X - 1位) ,如果设置为1,那么头后面是扩充位;
- CSRC计数 (CC – 4位) 包括紧跟在头后面的CSRC标识符数;
- 标记 (M - 1位) 是应用可用域;
- 有效载荷类型 (PT – 7位)标识RTP数据包的数据域的格式并用来确定应用对其的解释
- 序号(16位) 每发送一个RTP数据包,该值加1,接收者用来检测数据包是否丢失,以及决定正确的包顺序。
- RTP事件戳记(32位) 是第一个RTP字节的抽样时间。用于同步和jitter计算。
- SSRC ID(32位) 标识同步源,在RTP会话内随机选取;
- CSRC ID列表(从0到5*32位) 是一个可选的域,用来标识包中数据的源。CSRC ID的数量写在CSRC计数域中。
为了传输会话控制信息, RTCP foresees 几种数据包类型:
- SR, Sender Report, 用来承载发送者发出的信息,通知其他参与方应该接收控制信息(字节数、包数等);
- RR, Receiver Report, 承载有关会话参与者的统计,不包括活动的发送者;
- SDES, Source DESscription, 承载会话描述(包括CNAME 标识符);
- BYE, 离开会话的通知;
- AAP, 承载应用相关的功能,主要用来实验新应用。
每一个RTCP包都以一个类似于RTP的固定部分开始,然后是变长的结构性元素。多个RTCP包可以连结在一起,形成复合包(COMPOUND PACKET),另外,为了最大程度的统计分辨率,SR和RR包会比其他包发送的更频繁。