知行合一
全部博文(31)
分类: 系统运维
2009-07-05 10:59:55
在SIP环境中会被发送的基本的消息有:
大多数时间内,你会使用到REGISTER,INVITE,BYE还有CANCEL。而另外一些消息会被用在其他的特性当中。举例来说,INFO被用在DTMF
relay和通话中消息信息(mid-call signaling information)。PUBLISH,NOTIFY和SUBSCRIBE则用来支持列席系统(presence
systems)。REFER用来进行通话转接(call transfer)而MESSAGE则应用于一些聊天应用程序中。更新的消息也会随着协议标准化进程而随之出现。
像HTTP协议一样,这些消息的响应也会以文本形式出现。其中一些最终的响应消息被列在下图当中:
这一节将通过一个简单的例子来介绍一些基本的SIP操作。先让我们来诊视下图展示的两个用户代理之间的消息顺序。你可以看到伴随这RFC3665描述的会话建立过程还有几个其它的流程。
我们在这些消息上标上了序号。在这个例子中用户A使用IP电话向网络上的另外一台IP电话发出通话请求。为了完成通话,使用了两个SIP代理。
用户A使用称为SIP URI的SIP标识向用户发出通话。URI就像是一个电子邮件地址,比如sip:。一种可靠安全的SIP
URI也可以被使用,譬如sips:。使用SIPS建立的通话将会在主叫和被叫之间使用安全可靠的传输机制(TLS-Transport
Layer Security)
事务(transaction)的建立始于用户A向用户B发送INVITE请求消息。INVITE请求中包含一些特定头域。这些头域被称之为属性,为消息提供了额外的一些信息。包括唯一的标识,目的地,还有关于会话(session)的信息。
第一行是消息的方法名(the method name)。接下来是列出的头域。这个例子包含了所需要的头的最小集合。我们将在下面简要的描述这些头域。
l
VIA:它包含了用户A等待发出请求对应响应的所在地址。还包含了一个叫做“branch”的参数,这个参数用来唯一的标识这个事务(transaction)。VIA头将最近从“SIP跳”(SIP
hop)定义为IP,传输,和指定事务参数(The VIA header
defines the last SIP hop as IP,transport,and
transaction-specific parameters)。VIA专门用来路由响应消息。请求经过的每一个代理都会增加一个VIA头。而对于响应消息而言,相对于再次向定位服务器或是DNS服务器进行定位请求,使用VIA头进行路由将更加容易。
l
TO :它包含了名字(显示名(display
name))和最初选择的目的地的SIP URI(这里是sip:userB@sip.com)。TO头域不被用来路由消息包。
l
FROM:它包含了名字和表明主叫ID(caller
ID)的SIP URI(这里是sip:)。这个头域有一个tag参数,而这个参数包含了被IP电话添加进URI的一个随机字符串。是被用来进行辨识唯一性的。tag参数被用在TO和FROM头域中。作为一种普遍的机制用来标识对话(dialog),对话是CALL-ID和两个tag的结合,而这两个tag分别来自参与对话的双方。Tags在并行派生(parallel
forking)中作用显著。
l
CALL -ID:它包含了一个作为这通通话全局性的唯一的标识,而这个唯一标识是有一个随机字符串,来自IP电话的主机名或是IP地址结合而成的。TO,FROM的tag和CALL-ID的结合完整的定义了一个端到端的SIP关系,这种关系就是我们所知道的SIP对话(SIP
dialog)
l
CSEQ:CSEQ或者称之为命令序列(command
sequence)包含了一个整数和一个方法名。CSEQ数对于每一个在SIP对话中的新请求都会递增,是一个传统的序列数。
l
CONTACT:它包含一个代表直接路由可以联系到用户A的SIP
URI,通常是有一个用户名和FQDN(fully
qualified domain name)。有时候域名没有被注册,所以,IP地址也是允许使用的。VIA头告诉其他的组件向什么地方发送响应消息,而CONTACT则告诉其他组件向什么地方发送将来的请求消息。
l
MAX-FORWARDS:它被用来限制请求在到达最终目的地的路径中被允许的最大跳数(hops)。由一个整数构成,而这个整数在每一跳中将会递减。
l
CONTENT-TYPE:它包含了对内容消息的描述。
l
CONTENT-LENGTH:它用来告知内容消息的字节数。
会话的一些细节,像媒体类型和编码方式并不是使用SIP进行描述的。而是使用叫做会话描述协议(SDP
RFC2327)来进行描述。SDP消息由SIP消息承载,就像是一封电子邮件的附件一样。
过程如下:
话机开始并不知道用户B和负责域B的服务器的位置。因此,它向负责sipA域的服务器发送INVITE消息请求。发送地址在用户A的话机中进行设置或通过DHCP发现。服务器sipA.com也就是我们知道的域sipA.com的SIP代理服务器。
1. 在这个例子中,代理服务器收到INVITE请求消息并发送“100
trying”响应消息给用户A,表明代理服务器已经收到了INVITE消息并正在转发这个请求。SIP的响应消息使用一个三个数字组成的数字码和一条描述语句说明响应的类型。并拥有和INVITE请求一样的TO,FROM,CALL-ID和CSEQ等头域,以及VIA和其“branch”参数。这就使得用户A的话机同发出的INVITE请求联系在一起。
2. 代理A定位代理B的方法是向DNS服务器(SRV 记录)进行查询以找到负责sipB的SIP域的服务器地址并将INVITE请求转发给它。在向代理B(译者注:这里作者写的是proxyA,但是应该是B)发送INVITE消息前,代理A将其自己的地址通过VIA头添加进INVITE,这就使得用户A的话机同INVITE请求的响应消息联系在了一起。
3. 代理B收到INVITE请求,返回“100
Trying”消息响应,表明其正在处理这个请求。
4. 代理B查询自己的位置数据库以找到用户B的地址,然后将自己的地址也通过VIA头域添加进INVITE消息发送给用户B的IP地址。
5. 用户B的话机收到INVITE消息后开始振铃。话机为了要表明这种情况(振铃),发送回“180
Ringing”响应消息。
6. 这个消息以相反的方向路由通过那两个代理服务器。每一个代理利用VIA头域来决定向哪里发送响应消息并从顶部将其自己的VIA头去除。结果就是,180
Ringing消息不需要任何的DNS查询,不需要定位服务的响应,也不需要任何的状态处理就能够返回到用户那里。这样的话,每一个代理服务器都能够看到由INVITE开始的所有消息。
7. 当用户A的话机收到“180
Ringing” 响应消息后开始“回铃”,表明另一端的用户正在振铃。一些话机是通过显示一些信息进行表示的。
8. 在这个例子中,用户B对对方发起的通话进行了响应。当用户B响应时,话机发送”200
Ok“响应消息以表明通话被接起。“200 Ok”的消息体中包含了会话的描述信息,这些信息包括指定了编码方式,端口号,以及从属于会话的所有事情。作这项工作的就是SDP协议。结果就是,在从A到B(INVITE)和从B到A(200
OK)的两个阶段,双方交换了一些信息,以一种简单的“请求/响应”的模式协商了在这通通话中所需的资源和所需要的能力要求。如果用户B不想得到这通通话或是此刻处于忙线中,200
Ok将不会发出,取代它的是描述这种状况(这里是486 Busy Here)的消息。
第一行是响应码和描述信息(OK)。接下来是头域行。VIA,TO,FROM,CALL-ID和CSEQ是从INVITE请求中拷贝的。有三个VIA头,一个是用户A添加的,另一个是代理A添加的,最后一个则是代理B添加的。用户B的SIP话机在对话的双方加入了一个TAG参数,这个参数在这通通话的以后的请求和响应消息中都将出现。
CONTACT头域中包含了URI信息,这个URI信息是用户B能够直接被联系到他们自己的IP话机的地址。
CONTENT-TYPE和CONTENT-LENGTH头域先给出了关于SDP头的一些信息。而SDP头则包含了用来建立RTP会话的媒体相关的参数。
1. 在这个例子中,“200 Ok”消息通过两个代理服务器被送回给用户A,之后用华A的话机停止“回铃”表明通话被接起。
2. 最后用户A向用户B的话机发送ACK消息确认收到了“200
Ok”消息。在这里,ACK避开了两个代理服务器直接发送给用户B。ACK是SIP中唯一不需要进行响应的消息请求。两端在INVITE的过程中从CONTACT消息中了解双方的地址信息。也结束了INVITE/200
OK/ACK的过程,这个过程也就是我们所熟知的SIP三次握手。
3. 这个时候两个用户之间开始进行会话,他们以用SDP协议协商好的方式来发送媒体包。通常这些包是端对端进行传送的。在会话中,通话方可以通过发送一个新的INVITE请求来改变会话的一些特性。这叫做re-invite。如果re-invite不被接受,那么“488
Not Acceptable Here”响应就会被发出,但是会话不会因此而失败。
4. 要结束会话的时候,用户B产生BYE消息来中断通话。这个消息绕过两个代理服务器直接路由回用户A的软电话上。
5. 用户A发出“200
OK”响应消息以确认收到了BYE消息请求,从而结束会话。这里,不会发出ACK。ACK只在INVITE请求过程中出现。
有些情况下,在整个会话过程中,对于代理服务器来说,能够待在消息传输的中间位置来观察两端的所有消息交互是很重要的。如果代理服务器想在INVITE请求初始化完成后还待在此路径中,可以在请求消息中添加RECORD-ROUTE头。用户B的话机得到了这个消息,之后在其消息中也会带有这个头,并且会将消息发送回代理。记录路由(Record
Routing)在大多数的方案中都会被使用。
REGISTER请求是代理B用来定位用户B的方法。当话机初始化的时候或是在通常的时间间隔中,软电话B向在域sipB中的一个服务器(SIP
REGISTRAR)发送REGISTER请求。注册服务器(REGISTER)将URI与一个IP地址联系在一起,这种绑定被存储在定位服务器上面的数据库里。通常,注册服务器,定位服务器,和代理服务器在同一台物理机器上,并使用相同的软件。OpenSER就能够扮演这三种角色。一个URI只能够在一个特定的时间内由一个单独的机器注册。
理解“事务”(transaction)和“对话”(dialog)的区别是非常重要的。事务发生在一个用户代理客户端和另一个用户代理服务端之间,包含从第一请求到最后一个响应的所有消息。中间的阶段性的响应消息可以是以1开头的三位数字码(比如180
Ringing),最终的响应消息则是以2开头的三位数字码(比如 200
OK)。事务包括的范围由SIP消息中VIA头形成“堆栈”来决定。因此,用户代理在初始化invite后才不需要依靠DNS或位置表进行消息路由。
对话(Dialog)通常是从INVITE事务开始,由BYE事务结束。一个对话由CALL-ID头唯一标识。TO
tag,FROM tag和CALL-ID的结合来完整的定义。
按照rfc3665的描述,有11个基本的会话建立流程。其列出的并不一定是完整的,但是覆盖了最好的例子。前两个流程在这一章节中进行了阐述——“成功建立会话Successful
Session Establishment”和“通过两个代理建立会话Session
Establishment Through Two Proxies”。其中的一些流程的描述你将在其他阐述呼叫前传(call
forwarding)(譬如:“不接听导致没能成功建立Unsuccessful
with no Answer”和“忙音导致建立失败Unsuccessful
Busy”)的章节中看到。
译者注:应为Real Time Transport Protocol
实时传输协议是负责诸如音频和视频等数据的实时传输的。它标准化于RFC3550。使用UDP协议进行传输承载。为了能够被实时传输,音频或视频必须经过一定的编码打包。最基本的,该协议允许使用如下的一些特性对进出的数据包的媒体传输的时间和内容要求进行指定:
l
序号
l
时间戳
l
无重传机制的包的前转
l
源识别
l
内容识别
l
同步
与RTP相伴的协议叫做RTCP(Real
Time Control Protocol),被用作对RTP包进行监控。它可以度量延迟和抖动。
RTP协议描述的内容通常会由一种编码方式进行编码。没一种编码方式都有一种指定的用途。一些有压缩算法而另外一些则不需要。比较普遍的是使用不需要压缩的G.711编码方式。一个信道64Kbps的带宽要求需要一个高速的网络,通常在局域网(LANs)中比较常见。但是在广域网(WAN)中对于一个单独的声音信道来说,64Kbps的带宽购买起来比较昂贵。这时候诸如G.729和GSM等可以将声音包压缩至8Kbps的编码方法则可以节省很多的带宽。由Global
IP sound公司发明的iLBC编码方式则可以掩盖网络中由丢包造成的影响。在丢包率带到7%的情况下,使用iLBC仍然能够维持一个比较好的声音质量。所以对于你的VoIP提供商支持的编码方式你必须进行明智的选择。
在一些情况下,RTP协议被用来承载诸如DTMF的信号信息。RFC2833中描述了一种方法,这种方法就是将DTMF作为RTP协议中的命名事件(named
events)进行传输。在用户代理客户端和用户代理服务端之间使用同一种方法进行DTMF传输是非常重要的。
RTCP可以对接受的质量进行反馈。它为RTP媒体流提供带外控制信息。诸如抖动(Jitter),往返时延(RTT-Round
Trip Time),传输延迟(latency)和丢包等的数据可以使用RTCP进行搜集。RTCP通常用来对声音质量进行报告。
SDP协议在RFC4566中被进行了详细的描述。它是在用户代理之间进行会话参数协商之用的。媒体的细节,传输的地址还有其他与媒体相关的一些信息都使用SDP协议在用户代理之间进行交互。通常,INVTIE消息中包含了SDP“供给消息”,而200
Ok则包含了“回答消息”。这些消息会在下面的图中进行展示。在下图中,你可以观察到GSM编码方式被“供给”,但是另外一台话机却并不支持该编码,那么然后它将使用它本身支持的编码方式进行“回答”,在这个例子中它支持的是G.711
ulaw(PCMU)和G.729编码方式。 会话的“rtpmap:
INVITE (SDP Offer)
200 OK(SDP Answer)
理解声音相关协议的每一个协议对于OSI模型是属于哪一层也是相当重要的。
在我们开始深入的挖掘SIP代理之前,了解VoIP提供商的解决方案中的所有部件是非常重要的。服务提供者通常由多个服务器(servers)和多个服务(services)组成。这里说的服务可以根据规模的大小来决定是被安装在一台单独的服务器上还是安装在多台机器上面。
本书将在前几个章节中按照这张图从左到右来描述每一个部件。所有的章节中都将使用这张图来帮助你来了解你所处的位置何在。
SIP代理是我们解决方案中的核心部件。用来负责用户的注册和维护位置数据库(映射IP和SIP地址)。所有的SIP路由和消息都会被SIP代理处理,它也负责一些用户端级别的服务譬如呼叫前转,白/黑名单,快速拨号等。这个部件从不处理媒体(RTP包),所有与媒体相关的包都从用户代理客户端,服务器和PSDN网关直接路由。
用户管理和供给入口是一个重要的部件。在入口当中,用户订阅服务并且应该能够购买信用量,修改密码和验证他/她的账号。另一方面,管理者应该能够删除用户,改变用户信用级别,承认,删除权限。对于管理员来说,“供给(Provisioning)”过程使得用户代理如IP电话,模拟话机适配器还有软电话的自动安装过程更加容易。
为了能和公共的交换电话网络交互,PSTN网关是需要的。通常,这个网关是使用E1或T1中继线的PSTN的接口。在这个领域中使用最广泛的是来自Cisco,AudoCodes和Quintum公司的网关。Asterisk也占据了一定的市场份额,因为它的每个端口的价格要比竞争对手们便宜75%。如何评估一个网关的好坏,要检查它对SIP协议扩展的支持程度,譬如对RFC3515(REFER),RFC3891(Replaces)还有RFC3892(Referred
by)。这些协议使得我们能够在SIP代理背后进行呼叫转移;如果网关中不支持他们,进行呼叫转移是不太可能的事。
因为SIP代理从不处理媒体,所以如IVRs,语音邮箱,电话会议等和媒体相关的服务要能够在媒体服务中得到实现。由iptel开发的SEMS
SIP Express媒体服务器具有一些很好的特性,如conference,voicemail和announcements等。我们要再一次提到Asterisk,因为它也能够用来提供这些服务。
任何SIP服务提供者必须要为他的客户提供NAT穿透的解决方案。媒体代理就是一座帮助处在对称式防火墙(symmetric
firewall)之后的用户能够访问SIP服务提供者进行RTP连接的桥梁。如果没有了这些代理,服务提供者可能会流失35%的用户。你可以使用这些部件来实现一个通用的NAT穿透技术。媒体代理还可以帮助你进行记帐纠错,比如,因为某种原因,没有收到BYE消息而导致了SIP对话没有结束,结果记帐发生了错误等情况。
拥有一台安装了RADIUS的服务器是对通话进行记账的基本条件。SIP服务提供者对账单记录是最关心的。OpenSER可以被配置将一些记账信息发送到一台RADIUS服务器(比如Radiator或FreeRADIUS)上。SIP通话账单也可以被记录到数据库中。但是,这样将产生两条记录,而这两条记录需要手工进行核对。
RADIUS服务器可以记录关于通话时长的一些信息,但是却不能记录每通通话的资费信息。将资费信息应用到通话上是需要技巧的。这里我们使用AG项目组(cdrtool.agprojects.com)开发的被称为CDRTool的GPL工具。它负责将资费应用到通话上面。
最后我们需要一些监控,故障检修和测试的工具来帮助我们定位并解决在SIP服务器上发生的一些问题。首当其冲的当然是协议分析工具,在余下的章节中我们将能够看到如何使用ngrep,ethereal和tethereal。OpenSER有一个被称为SIP
trace的模块,我们也将使用到。
SIP协议最好的参考资料就是RFC3261。阅读RFC确实有点沉闷(不过如果你有点失眠这确实是一种好办法)。你可以在上找到它。也可以在哥伦比亚大学的网站上找到好的SIP教程如:。也可以在上找到许多关于SIP的信息。
一个非常好的教程在iptel的网站上:。
下面是一个叫做SIP应用者(SIP
implementors)的邮件列表,你可以在上面就SIP的知识进行提问:。
这一章你已经学到了什么是SIP协议以及SIP协议的功能。也知道了诸如SIP代理,SIP注册服务器,用户代理客户端,用户代理服务端,PSTN网关等SIP协议中的部件。还看到了SIP的体系结构,主要的消息和处理过程。以及去什么地方可以找到更多相关的信息。