RFC3261(4 范例)

 

这节通过简单的示例介绍了SIP的基本操作。本节实际上是一个指导手册,没有包含任何的标准状态。

第一个例子说明了SIP的基本功能:终端定位、通信意愿、待建立会话的协商、已建立会话的关闭。

图一表示一个典型的两个用户(Alice和Bob)间的SIP消息交易交换例子.(每一个消息采用字母”F”和一个用来指向正文的一个数字做标记)。在这个例子里,Alice使用她PC上的一个SIP的应用程序(比如说一个软的电话), 通过Internet呼叫Bob的SIP电话。这个例子也演示了两个SIP代理之间,怎样为Alice和Bob建立会话。这种典型的应用通常被称为"SIP四边形", 在图1中采用虚线画出.

    Alice 通过Bob的SIP用户ID “呼叫” Bob, 这个SIP用户ID被称为SIP URI(Uniform Resource Identifier)。SIP URI在19.1节中定义。它很像一个email地址,典型的SIP URI包括一个用户名和一个主机名。在这个范例中,SIP URI是sip:bob@biloxi.com,biloxi.com是Bob的SIP服务提供商的域名。Alice也有一个SIP URI: sip:alice@atlanta.com。 Alice可能输入Bob的URI,也可能直接在地址本的一个超级链接上点击一下Bob的URI。SIP也提供安全URI,称作SIPS URI。例如:sips: bob@biloxi.com。 一个基于SIPS URI的通话保证这个通话是安全的,并且对呼叫者和被叫的所有的SIP消息是加密传输的(即TLS)。在TLS中,请求是通过加密方式传输给被叫方,但是这个加密机制是基于被叫方宿主的实现的。

    SIP是基于一个类似HTTP协议的请求/应答的事务模式。每一个事务包括一个请求(该请求调用一个特定的Method或者Function),并且至少一个应答。在这个范例中, 事务开始于Alice通过软电话向Bob的SIP URI发送的INVITE请求。INVITE是一个SIP请求Method的例子,表示请求方(Alice)希望服务方(Bob)应答。INVITE请求包含一系列的头域。头域中包含很多属性,这些属性提供了消息的附加信息。在INVITE中唯一定义了如下的字段:呼叫的唯一标志,目的地址,Alice的地址,Alice和Bob建立会话的类型。INVITE请求(图1中的F1)看起来如下:

 

INVITE sip:bob@biloxi.com SIP/2.0

Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds

Max-Forwards: 70

To: Bob <sip:bob@biloxi.com>

From: Alice <sip:alice@atlanta.com>;tag=1928301774

Call-ID: a84b4c76e66710@pc33.atlanta.com

CSeq: 314159 INVITE

Contact: <sip:alice@pc33.atlanta.com>

Content-Type: application/sdp

Content-Length: 142

(Alice’s SDP not shown)

  

图一:SIP矩形表达的SIP会话建立例子。

 

    在文本消息的第一行,包含了请求的Method(INVITE)。该行之后是这个请求的头域。这个例子中包含了最少需要的头域集合。简单介绍一下:

    VIA 包含了一个地址(pc33.atlanta.com), Alice期望通过该地址接收所发送请求的响应。还包含了一个branch参数来标志当前事务。

 

    TO 域包含了显示名(Bob)和一个SIP或者SIPS URI(sip:bob@biloxi.com),该URI是请求最初要发送的地址。显示名在RFC 2822中有描述。

    From 域也包含一个显示名(Alice)和一个SIP或者SIPS URI(sip:alice@atlanta.com),该URI用来标志请求的原始发起者。该域也包含了一个tag参数,这个tag参数是一个随机字符串(1928301774),被软电话添加到URI上,起标志作用。

    Call_ID 域包含一个全局的唯一标志,用来唯一标志这个呼叫,通过随机字串和软电话的名称或者IP地址混和产生。通过TO域的tag参数, FROM域的tag参数和CALL-ID完整定义了Alice和Bob之间的端到端的SIP关系,并且被称为一个对话。

    CSEQ (Command Sequence)包含了一个整数和一个请求名字。在对话中每发送一个新的请求,这个Cseq就会顺序递增。是一个传统的序列数。

    Contact域包含一个SIP或者SIPS URI,用来表示访问Alice的直接地址,通常由用户名(用户名采用FQDN(合格域名/全称域名)形式)组成。当FQDN作为首选的时候,许多终端用户由于没有注册域名,因此允许使用IP地址。VIA域告诉其他节点请求的应答发送到哪里,Contract域告诉其他节点将来的请求发送到哪里。

    Max-Forwards 最大转发数量限制了通讯中转发的数量(跳数)。它是由一个整数组成,每转发一次,整数减一。

    Content-type包含了消息正文的描述(消息正文在本范例中没有列出)

    Content-length 包含消息正文的长度(字节数)

    完整的SIP包头域的定义在20节。

     会话的细节,比如媒体的类型,编码方式,或者采样速率,没有通过SIP来描述。这个可以通过其他的协议, 在正文中进行描述。有一种是会话描述协议(SDP)(RFC2327[1])。这个SDP消息(没有在例子中列出)通过SIP消息承载发送,就像发送EMAI的附件一样,或者说通过HTTP传输的网页一样。

    由于软电话并不知道bob的位置, 或者biloxi.com域里的sip服务器在哪里,所以软电话发送INVITE请求到Alice的sip服务器所在域,atlanta.com。假定这个atlanta.com SIP服务器地址已经在Alice的软电话中被配置了,或者可以通过DHCP获得。

    atlanta.com SIP服务器是一台代理服务器。代理服务器接收SIP请求并且代表请求者转发。在这个例子中,代理服务器接收到INVITE请求,并且回送一个100(Trying)应答给Alice的软电话。100(Trying)应答表示INVITE请求已经收到,并且代理服务器正在转发INVITE请求。SIP的应答是通过一个三位数的数字表示的。SIP应答包含了与INVITE请求通的TO、FROM、Call-ID,CSEQ和VIA中的branch参数,这使得Alice的软电话可以把请求和应答关联起来。atlanta.com代理服务器收到INVITE请求之后,就去找biloxi.com域的代理服务器, 可能通过DNS服务来找这个SIP服务器。这在[4]中有描述。最后,转发INVITE请求到biloxi.com或者能到达biloxi.com的代理服务器。在转发请求之前,atlanta.com代理服务器会在via头上增加自己地址(INVITE已经在VIA中包含了Alice的的地址)。biloxi.com代理服务器收到这个INVITE请求并且返回一个100(Trying)应答给atlanta.com代理服务器, 标志着它已经收到这个请求并且正在处理这个请求。这个代理服务器通过查询数据库,通常叫做位置服务器,这个服务中包含了bob的当前ip地址。(我们在下一节可以看到这个数据库是怎么回事)。biloxi.com代理服务在VIA中增加自己地址并且发送它到bob的sip 电话。

    Bob的SIP电话接收到INVITE请求并且提醒bob有一个从Alice的来电,这样bob可以决定是否响应这个来电。比如这样一个场景:bob的电话响了。bob的sip电话发送一个180(Ringing)回应,这个回应将通过两个代理服务器原路返回给Alice。每一个代理服务器通过via头域决定该把这个应答发送给哪里,并且在发送之前把自己的地址从头上拿走。虽然DNS和定位服务在路由最初的INVITE请求时是必须得,180(ringing)响应可以简单返回给发起者而不需要查找发起者在哪里,并且不需要在代理服务器保留状态,同时,每一个转发INVITE的代理也可以得到INVITE的每一个应答,这样的特性也非常有用。

    当Alice的软电话收到180(Ringing)应答的时候,它提示Alice,可能是通过一个回铃音,或者屏幕上的一个消息提示。

    在这个例子中,Bob决定应答这个呼叫。当他拿起电话,他的SIP电话发送200(OK)回应给发送者,表示这个电话已经接起来了。这个200(OK)包含了一个消息体,这个消息体包含SDP媒体描述,这个媒体描述包含Bob希望和Alice建立何种会话连接。同样,SDP消息也是两段交换:Alice发送一个给Bob,Bob发送一个回给Alice。这中两段交换提供基本的协商能力,并且基于简单的SDP提出/应答交换模型。如果Bob不想应答这个呼叫或者正在应答别的呼叫,一个错误的响应会代替正常的200(OK)回送出去,这样,就不会有媒体会话建立。SIP完整的响应码在21节有介绍。Bob发出的200(OK)(图一的F9消息)可能是这样的:

SIP/2.0 200 OK

Via: SIP/2.0/UDP server10.biloxi.com

;branch=z9hG4bKnashds8;received=192.0.2.3

Via: SIP/2.0/UDP bigbox3.site3.atlanta.com

;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2

Via: SIP/2.0/UDP pc33.atlanta.com

;branch=z9hG4bK776asdhds ;received=192.0.2.1

To: Bob <sip:bob@biloxi.com>;tag=a6c85cf

From: Alice <sip:alice@atlanta.com>;tag=1928301774

Call-ID: a84b4c76e66710@pc33.atlanta.com

CSeq: 314159 INVITE

Contact: <sip:bob@192.0.2.4>

Content-Type: application/sdp

Content-Length: 131

(Bob’s SDP not shown)

 

    应答的第一行包含了应答码(200)和短语(ok)。剩下的行包含了头域。VIA,TO,FROM,CALL-ID,Cseq头域是从INVITE请求包中直接拷贝过来的。(有三个VIA域值-一个是Alice SIP电话增加的,一个是atlanta.com代理加的,一个是biloxi.com代理加的)。Bob的SIP电话给TO域增加一个tag参数。这个TAG参数会被两个终端整合到对话中,并且在以后的对话中被使用。Contract域包含了一个能直接联系到Bob的URI。Content-type和Content_Length域涉及到消息体(没有在例子中体现),这个消息体里边是Bob的SDP媒体信息。

    除了DNS和位置服务之外,代理服务器可以灵活的自主决定路由,也就是说自己决定应该向哪里转发请求。比如,如果Bob的SIP电话返回一个486(电话正忙)信号,biloxi.com这个代理服务器可以转发这个INVITE请求到Bob的语音邮箱服务器。一个代理服务器可以同时向N个地方发送INVITE请求。这种并发寻找就是传说中的分流(forking)。

    在这个例子中,200(OK)应答通过两个代理并且发送到Alice的软电话上,Alice的软电话收到这个应答,停止振铃,并且提示电话已经被Bob接听。最后,Alice的电话发送一个确认消息,ACK,到Bob的SIP电话来确认接收到了这个最后的200(ok)应答。在这个例子中,ACK响应是直接由Alice的软电话发送到Bob的SIP phone上,绕过了两个代理服务器。这是因为两个终端(Alice和Bob)通过INVITE/200(OK)的请求应答包中的Contact包头域都知道彼此的地址了,这个地址在最开始发起INVITE请求的时候是不知道的。所以,不需要两个代理服务器再查找对方的地址了,所以代理服务器不参与接下来的通话流了。这就完成了一个完整的使用INVITE/200/ACK 三方握手来建立SIP会话的过程。会话建立过程的细节描述在13节描述。

    现在,Alice和Bob的媒体会话开始了,他们发送媒体包, 该媒体包采用之前建立会话过程中通过交换SDP包而约定的协议。一般情况下,端到端的媒体包和SIP信号控制包通过不同的通讯路径来发送。

    在会话中,Alice或者Bob都可能改变他们自己的媒体会话属性。这个可以通过发送一个包含新媒体属性描述的re-INVITE请求来完成。这个re-INVITE是参考一个现有的对话的,这样参对方明白这是要改变现有的会话属性而不是新建立一个会话。对方收到这个re-INVITE请求后,会发送一个200(OK)应答表示接受这个改变。请求方通过一个ACK来表示接受了对方的这个200(OK)应答。如果对方不同意这个媒体属性变化,他会发送一个错误的应答比如488(不被接受),这个也会收到发起者的一个ACK响应。不管怎样,就是re-INVITE的失败不会影响到现有的会话-原有的会话还可以用上次的媒体会话属性继续。可以在14节找到会话属性更改的细节说明。

    在通话结束的时候,Bob首先断开(挂机),并且发送一个BYE的消息。这个BYE消息将直接送到Alice的软电话,同样是绕过代理的。Alice通过发送200(OK)应答来确认收到了这个BYE消息,这个消息终止了会话并且应答了BYE事务。ACK在这里不需要发送-一个ACK信号只在作为一个INVITE请求的响应的时候才被发送。我们之后会讨论这个INVITE的特别处理,这点主关系到SIP的可靠性机制,一个通话的时间可能认为包含电话振铃和分支处理的时间。基于这样的原因,SIP请求的处理通常根据是否INVITE请求进行分类,INVITE类和非INVITE类请求分开处理。结束会话的细节可以在15节查到。

24.2节描述了图1中使用的全部消息详细解释。

    在某些情况下,代理可能看见所有终端间在会话期间的所有消息会很有用。比如,如果biloxi.com代理服务器希望在INVITE之后继续保持SIP消息路径,他会在INVITE中增加一个头域(Record-Route)包含一个URI指向这个代理服务器的主机名或者IP地址。这个消息会被Bob的SIP电话和Alice的软电话所接收(因为Record-Route头域将在200(OK)应答中被送回),并且在对话中一直保存。那么biloxi.com代理服务器就可以继续接收和转发ACK,BYE,给BYE的200(OK)应答。每一个代理都可以单独决定是否接收INVITE以后的后续消息,并且这些后续消息都可以被发送到那些决定接收后续消息的代理服务器。这种情况通常发生在提供mid-call(在通话进行中在座机和手机之间转换)业务的代理服务器上。

    注册是另一个常用的SIP操作。注册服务是biloxi.com代理服务器知道Bob当前地址的一个方法。在初始化的时候,并且每隔一段时间,Bob的SIP 电话发送REGISTER消息给biloxi.com域中的一个注册服务器。REGISTER消息包含了Bob当前使用设备的SIP或者SIPS的URI(sip:bob@biloxi.com)(转换成为Contact域中的SIP或者SIPS URI)。注册服务器将这个关联,也被叫做绑定,写到一个数据库里边,叫做位置服务,这个数据库可以被biloxi.com的代理服务器使用。通常登记服务器和代理服务器是部署在一起的。一个很重要的概念就是SIP服务器的差别在逻辑上,并非在物理上。

    Bob并没有被限定只注册一个设备。比如,他家里的SIP电话和公司的SIP电话都可以注册。这些消息在位置服务中保存,并且允许代理服务器通过不同的手段查找Bob。同样的,不同的用户也可以同时注册一个设备。

    位置服务是一个抽象概念。他通常让代理服务通过输入一个URI来查询到底应该向哪里转发请求。注册服务是创建这种消息的一种方式,但并非唯一。任何的映射功能都可以被配置来实现位置服务。

    最后在SIP中需要注意的是,注册服务只是用来路由收到的SIP请求,它并不做外发请求的身份认证。在SIP中授权和认证可以通过建立在基于挑战/应答模式上的每个请求来实现,也可以使用更底层的方式来实现(具体在26节有描述)。

    完整的注册SIP消息描述例子在24.1节。

    其他SIP的操作,比如检查SIP服务器的功能,或者客户端使用可选项(OPTIONS),或者用CANCEL取消一个未决的请求,在后续的章节中会介绍。

posted @ 2012-10-22 22:47  坐看风起云涌  阅读(522)  评论(0编辑  收藏  举报