live555多线程实现

来源:互联网 发布:白宫陷落 知乎 编辑:程序博客网 时间:2024/06/05 20:28
        接触过live555的童鞋都知道,live555是单线程的,用的是select模型;前几天预研了下多线程改造的问题,select模型受限于FD_SETSIZE,然后看到 下面一段注释:
/* * Select uses arrays of SOCKETs.  These macros manipulate such * arrays.  FD_SETSIZE may be defined by the user before including * this file, but the default here should be >= 64. * * CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST BE * INCLUDED IN WINSOCK2.H EXACTLY AS SHOWN HERE. */#ifndef FD_SETSIZE#define FD_SETSIZE      64#endif /* FD_SETSIZE */
         这段注释是windows WinSock2.h文件里的,只要修改FD_SETSIZE就提高MediaServer的路数了,想想项目中估计最多也就100路,顿时喜出望外,这样就不用像一些文章那样那么复杂地改造成多线程了,so easy ;
       如果剧情到这就结束了也就没有lz这篇blog了,下面就是大家喜闻乐见的情节:
       有一次跟群里的童鞋扯淡,聊到live555多线程问题,这位童鞋表示即使改了epoll也没有解决问题,然后lz就一脸懵B了,果然还是too young too simple...
       如果改了epoll也无法提高连接数,那么问题应该就不是出在select模型FD_SETSIZE的限制了,估计是单线程的时间片不够用了,提高线程优先级可以增加单线程的执行时间,应该有一点点效果,不过增加的路数也是有限;于是只能继续度娘......
       找到一篇稍微靠谱点的blog:https://my.oschina.net/u/2430809/blog/684648 
       这篇文章思路是很清晰的,连接处理交给live555的main线程,其他处理工作交给live555的sub线程,main线程和sub线程拥有独立的env; 按这里的思路实现后连接成功,但是由于这些线程都是在一个RtspServer下工作,会共享一些全局变量,多测试几次后,mediaserver偶尔就会崩溃; 抓dump改了几个bug之后还是有问题,本宝宝就不开心了,有问题没关系可以改,但是如果问题时不时冒出来,每次改一些代码细节,不确定性太大,对程序的稳定性也会有影响;相信这篇文章的博主一定比lz更熟悉live555,也更细心;但是反过来说,细节改得越多,风险也就越大(其实lz就是怕麻烦,哈哈哈)。
       到了这里,如果不用上面blog的办法,又该如何实现live555多线程呢?
       其实lz在之前预研的时候就考虑过一些办法,比如说 多进程+主进程调度 模式,有点类似上面博主的文章,就是单开一个进程接收连接,然后多开几个live555处理进程,监听端口可以随便设,反正用不到,比如说8554,8555,8556什么的;但是lz没有去实现,开几个无用的监听端口总是觉得怪怪的,还有就是多进程在linux下感觉还行,windows下总觉着很不舒服,应该有更好的实现方式:
       多进程优化:
       lz想既然linux线程就是使用轻量级的进程,linux可以这么用,lz当然也可以这么用,而且live555单进程的时候只有一个线程,多个rtspserver放在同一个进程里那不是so easy么,而且每个rtsp只维护自己的连接,互不干扰,也不用改live555里的源码,程序稳定性也是有保障的;
       端口监听及fd传递优化:
       关于端口监听,lz刚开始想到的是把 rtspserver中的incomingConnectionHandler函数直接 return 0 ,防止有数据从这个无效的监听端口过来,导致程序异常;然后想了好久没有想到什么好办法把fServerSocket监听去掉,eventloop在没有连接的时候总要有点活干吧,就暂时搁置了这个问题;然后思考main线程accept后如何把fd和clientaddr传给不同的live555数据处理线程,突然发现有一个东西在这里很好用----PIPE。主线程accept之后的socketclientaddr数据通过pipe传递给live555数据处理线程,刚好pipe fd又可以被select,这样的话用pipe fd代替fServerSocket,然后把incomingConnectionHandler函数改为virtual,在DynamicRTSPServer中重写incomingConnectionHandler函数,实现对pipe数据的解析;这样不仅解决了数据传递问题,还解决了无效监听端口问题,一举两得,皆大欢喜;
      下面是简单的流程图(talk is cheap, show you the picture):

    

       ps: 

       1.windows下 pipe是不支持select监听的,可以用socket模拟,参考:

        http://blog.csdn.net/g1036583997/article/details/52514192

       2.lz用testRTSPClient.cpp进行测试,10个live555线程,开了200多路client,并发是正常的,但是看打印数据量没有预期那么多,再用vlc测试,视频播放是正常的,估计是后面的码率变低了的关系;也有可能程序有问题,不过暂时没办法验证;
       3.欢迎拍砖,不打脸就行;




0 0
原创粉丝点击