跨平台、高性能的媒体转发服务器实现
2016-01-23 17:54
232 查看
最近实现了一个媒体转发服务器,代码可以编译成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客户端一般是躲在内网,要跨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++语言开发。
本文所讨论的服务器在实现后已经部署在实际环境使用,效果良好。
相关文章推荐
- 60个开发者不容错过的免费资源库
- hdu 3364(异或方程的高斯消元)
- 服务器之间建立信任关系
- 多线程实例
- I am back-电商网站开发&jQuery
- 字符编码
- HTML学习笔记——(一)HTML简介
- 【BLE】CC2541之OAD
- Protobuf Lesson 1: compile
- 如何建立自己的技术壁垒
- python fabric模块
- 通讯录实例
- hdu1128 Self Numbers
- leetCode 242. Valid Anagram
- Php发送post请求方法
- iis7.5加fck解析漏洞后台拿shell
- echo,die(),print(),print_r(),var_dump()的区别
- Mysql数据库字符集问题
- 作为一个前端,可以如何机智地弄坏一台电脑?
- 彻底解决mysql中文乱码的办法