一个关于Darwin Streaming Server 访问次数的缺陷

一个关于Darwin Streaming Server 访问次数的缺陷

                                   

先给大家简单介绍一下这个问题的背景,在实际的应用中遇到这样一件事,客户端使用RTSP请求访问服务端的视频信息,服务端使用的是Darwin Streaming Server。每天早上重启一下服务,白天可以正常运行,但是过了一个晚上,第二天早上过来看,程序就不正常了。进一步了解到,有客户端在晚上的时候会通过轮询方式访问视频信息。系统环境为客户端使用的Window 7,服务端使用的是Windows2008 server。

 

为了解决这个问题,费了好些功夫,大概花了一周左右的时间进行调试。最终发现了一个关于Darwin Streaming Server访问次数的的缺陷。

 

下面讲一下调试过程。

 

首先,我默认认为应该不是转发的问题,所以就从客户端上下功夫。客户端原本连接方式是每次请求为一个短链接。实际运行效果很快就会发生上述问题,后来改成每一个RTSP 会话为一个长连接,这样效果比之前好一些,但是依然会出现失败的情况,感觉找不到头绪。

 

然后,我想到是不是网络问题引起的,因为经常晚上打开程序,早上就会有报错现象。为了排查这个问题我将服务端和客户端放到了一台机器上进行测试。依然有问题,排除网络原因。  

 

既然不是网络原因,还是从程序入手。写测试程序快速发送请求包。果然在大约7000次左右就会出现访问失败的情况。每次都很有规律。既然能快速重现,我想应该就比较好解决了。

 

我将该现象在多个技术群里发了一遍,求助大家。大家反映没有遇到过,无解。还是自己来吧。先调客户端程序,Darwin的调试实在比较复杂,通过抓包测试发现客户端发送消息都成功了,在服务端也收到了客户端发送请求包,但是服务端程序没有反应。难道是发送的消息有问题,Darwin对客户端发送的端口号作了限制?死马当作活马医吧,我在客户端试着绑定客户端发送端口,再次测试。等待结果... ... 结果出来了。现象已旧。因为客户端是用ACE框架写的,是不是ACE本身隐藏的缺陷?我将这个疑问,发送群里。别人建议我还是不要用ACE,ACE确认可能存在一些缺陷。在没有别的想法的时候,我决定先修改客户端。改成使用Windows底层Socket的方法来发送消息。再次期待... ...再次失望。

 

我终于推翻自己最初的想法。决定应该在服务端找办法。单步跟踪调试Darwin, 发现连接事件和发送包消息的事件,Darwin都能捕获到。但是不知道为什么就不能进入RTSPSession的Run。于是再次查找Darwin相关资料。了解其核心消息机制。在此期间边看便调试。

 

通过跟踪调试,找到这样一个消息机制。

Socket的读取都在EventContext类中的EventThread线程中,具体到EventThread::Entry()中的select_waitevent()捕获。

下面看一下这个函数。

 

捕获到Socket的事件后,会在EventThread::Entry()函数中查找EventThread::fRefTable,获取对应的EventContext。如果是RTSP请求消息,那么,得到的是EventContext类型的派生类RTSPListenerSocket。在对应的ProcessEvent()中accept Socket,每一个RTSP线程会创建一个。

 

下面我们接着看ProcessEvent()这个函数。根据派生关系,应该会进入下面的函数。void TCPListenerSocket::ProcessEvent(int/*eventBits*/)。

 

经过多次调试,发现问题就出现在theSocket->RequestEvent(EV_RE);这个函数中,我们先看一个这个函数做了什么?

这个函数要将RTSPSocket对应加入EventThread::fRefTable中,每次请求会先申请一个UID,申请方式是通过compare_and_store(8192 , WM_USER,&sUniqueID)生成的,然后会将这个UID和与RTSPSocket绑定,并加入到映射表中,而UID实际作用是通过窗口接收消息的唯一ID。这样在收到客户端发送的RTSP请求时,先在EventThread::Entry()捕获到消息,然后根据UID在fRefTable中查找对应的Socket对象。所以消息的类型实际上是依赖于UID这个值的。但是我们看上面那段代码,在生成UID的时候使用方法是循环获取ID的方式。具体可以查看compare_and_store代码?当请求次数足够多的时候,会发现UID有从头开始。这样由于之前的部分UID肯定会被占用掉,已经和其它Socket对应绑定了。所以通过新生成的UID在fRefTable表中获取的Socket对应必然是不对的。为了解决这个问题。我们需要先判断一下这个UID是否被占用,如果被占用了就不能再使用。

 

具体改动如下,在EventContext::RequestEvent(int theMask)的函数中增加判断UID是否被占用的逻辑。具体判断方式还是使用到了fRefTable这个参数的特性,不清楚的可以仔细阅读一下OSRefTable类的说明。

 

通过以上改动,重新编译运行。通过压力测试一切正常。本人对Darwin Steaming Server还不是非常熟悉,不足之处请大家原谅。

 

 

 

火烧云  2015年2月2日于北京

 

   

      

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QTSS服务器是当今三大流媒体服务器之一,其开源的版本是darwin streaming server。作为三大主要流式媒体应用中唯一一个开放源代码的产品,DSS让开发人员能够研究流媒体最底层的技术,大幅度提高设计水平。事实上,当前国内外许多公司正是在DSS的基础上开发了自己的流式媒体相关产品。但是DSS源码量比较大,简单统计一下5.5版本总共大约13万行代码,虽然DSS源码组织结构很好,但是入门的门槛还是比较高。 为降低入门门槛,首先要做的就是把DSS源码简化,下面简单介绍一下我对5.5版本裁剪优化的过程。 从网上下载到5.5版的源码,整个压缩包有20多兆,解开压缩包,里面有很多测试用的多媒体文件,实际代码小很多。 用VC6打开WinNTSupport子目录下的工程文件StreamingServer.dsw。选FileView标签页展开 StreamingServer files模块前面的加号,可以看到主程序依赖四个模块分别是 CommonUtilitiesLib APICommonCode APIStubLib SafeInternalStdLib QTFileLib,再点开这几个模块前面的加号,可以看到整个工程就只依赖这几个模块。把不用的其他模块统统的删掉,好畅快淋漓哦。庞大的DSS现在只剩下6个大模块了。 分大模块点开所有的文件,鼠标光标自动在每个文件的顶端,所有文件都按两下回车,再一起保存,为的是把工程需要的文件做个时间标记,所有修改时间不是当前的文件都是没有实际使用的文件。 哈哈,有很好的办法去除实际不使用的文件,在资源管理器中搜索DSS目录下的所有.h文件,把修改时间不是当前时间的文件统统删掉。同样的办法处理一遍.c文件和.cpp文件。 再在资源管理器中遍历DSS目录下的所有子目录,把即没有.h文件,有没有.c文件或.cpp文件的子目录统统删掉。 大话西游的经典台词出来了,"整个世界清净了"。 再设置StreamingServer files为Active project,编译一下。 哈哈,一次编译通过,刚才的一阵狂砍乱剁中没有删掉有用的文件。再接再励,顺便把那些即不是源码又不是VC工程文件的文件删掉,DSS现在好小巧苗条哦。 再大概统计一下源代码总共大约8.9万行,实际程序代码5.4万行。如果再删掉编译要用但最小程序不使用的如mp3,http等模块,最后可以减到4万行左右。 代码初步简化完了,就得安装程序跑跑看效果,如果上网方便可以在网上找到很多安装的教程。如果上网不方便,按照程序提示也能做好。 在VC6 IDE开发环境中点击run按钮,程序运行有提示: Darwin Streaming Server must either be started from the DOS Console using the -d command-line option, or using the Service Control Manager 看提示在命令行带-d参数再运行程序,程序有提示: Fatal Error:Could not load configuration file at c:\Program Files\Darwin Streaming Server\streamingserver.xml 很明显提示少了streamingserver.xml文件,在Darwin目录下搜streamingserver.xml文件,已经有此文件了,那就按照提示把streamingserver.xml文件拷贝到c:\Program Files\Darwin Streaming Server目录下。既然是xml文件,就用文本打开看一下了,里面好多c:\Program Files\Darwin Streaming Server\XXX 这样的路径,那就按照这些提示把相关路径都建好。 聪明的大家看到Movies子目录了,放电影的地方嘛,接着把DSS源码附带的*.3gp文件和*.mp4文件拷贝到此目录,如果担心放错目录,那就在Darwin Streaming Server目录和所有子目录中都放媒体文件。 再开VLC,用打开网络串流的方式打开 rtsp://localhost/sample_100kbit.mp4 文件。 哈哈,大功告成。 以后就是各位网友优化dss源码的事情了。祝各位网友顺顺利利地看懂源码,做出更牛牛的流媒体服务器。 来自:http://www.cnblogs.com/mcodec/articles/1735765.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值