跨平台、高性能的媒体转发服务器实现

最近实现了一个媒体转发服务器,代码可以编译成windows(64位或32位,可以编译为service),Linux,Mac OS X等多种平台下的程序。

sip客户端一般是躲在内网,要跨nat如果采用stun一类的技术,除了客户端麻烦外,需要部署stun服务器,而且不能解决所有类型的nat,最佳解决方案是部署一个支持媒体转发的全代理服务器,运营商的IMS网络,在网络边缘部署的SBC--会话边界控制器--功能众多,其中主要功能也是完成媒体转发。

媒体数据包括音频、视频数据,一般采用rtp/udp发送,数据量巨大,软件设计上要有较高效率,否则单机支持的并发数较低,实用性就会很差。

转发的逻辑如下:

1、服务器的一个逻辑通道A收到呼叫(INVITE消息)后分析消息中的sdp数据,取出对方的ip地址,audio端口,video端口(如果有的话),rtcp端口(如果有的话);

2、启动另外一个逻辑通道B发出呼叫,注意INVITE消息中的sdp内容要进行替换,即sdp中的ip地址,audio端口,video端口(如果有的话),rtcp端口(如果有的话)等分别替换成本通道的对应地址和端口;

3、如果B通道收到对方发来的sip应答消息,要通过A通道转发;如果消息中带有sdp,则取出对方ip和端口号,转发sip信令时分别进行地址替换;

4、在A通道和B通道侦听本地端口,即audio,video,rtcp的端口,如果收到数据,则转发到相连通道的目标地址端口,如A通道收到的audio数据发到B通道的audio目标地址,反之亦然;

5、任何通道收到BYE信令消息,结束侦听端口,并将信令通过相连通道进行消息转发。


如何侦听数据并转发呢?

最简单方式是每个端口侦听时就创建一个线程,在接收udp数据时堵塞住,直到有数据到达就进行转发,结构很简单,但这样效率太低,考虑1000路并发,每个呼叫占用2个通道,每个通道侦听audio,video,rtcp等3个端口,则需要6000个线程,这是不可想象的。且不考虑线程切换的效率,在32位windows下甚至不会有足够的内存来创建如此多的线程,因为每个线程默认将要使用2M内存用以作为线程堆栈。

我采用了线程池的方式。即创建有限的线程,每个线程处理一批udp的socket句柄,在不同的操作系统下采用不同的方式判断是否有数据到达:

   select -- windows下,此种方式不能处理太多的句柄;

   epoll -- linux下,可以处理大量句柄,而且效率较高;

   Kqueue -- os x下,类似epoll, 可以处理大量句柄,而且效率较高

和蓝星际语音平台使用的媒体库不同,媒体转发服务器不需要录音,放音,会议等功能,不需要对媒体数据进行编码或解码,因此占用的cpu不高,也没有磁盘io。所需要的是更大的网络带宽,更快的网卡。


最后,我们还实现了跨平台的sip信令服务器,该服务器来负责客户端的注册,信令的转发判断。在信令服务器上,可以自动感知媒体转发服务器的注册和注销,并进行负载均衡。

这两个服务器均使用了我们自行开发的蓝星际sip协议栈,均使用C/C++语言开发。

本文所讨论的服务器在实现后已经部署在实际环境使用,效果良好。

你可能感兴趣的:(实现,sip,rtp,媒体,跨平台,转发)