2022年Apple公司Darwin流式服务器源代码分析[借 .pdf
《2022年Apple公司Darwin流式服务器源代码分析[借 .pdf》由会员分享,可在线阅读,更多相关《2022年Apple公司Darwin流式服务器源代码分析[借 .pdf(25页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、Apple 公司 Darwin 流式服务器源代码分析(尉明)当前,伴随着 Internet 的飞速发展,计算机网络已经进入到每一个普通人的家庭。在这个过程中,一个值得我们关注的现象是:Internet中存储和传输内容的构成已经发生了本质的改变,从传统的基于文本或少量图像的主页变为大容量、富信息量的流式媒体信息。一份早在1998 年提交的研究报告就曾指出,流式媒体统治 Internet的潮流是不可抗拒的,该报告估计到2003年,存储在网络服务器上的内容超过 50%的将是流式媒体信息。但今天看来,这个估计还是有些保守了。所谓的流式媒体简单的讲就是指人们通过网络实时的收看多媒体信息:如音频流、视频流
2、等。与流式媒体对应的传统工作方式是下载+播放模式,即用户首先下载多媒体文件,然后再在本地播放,这种方法的一个主要缺点是启动延迟较大,例如一个 30 分钟长的 MPEG-I 文件(相当于 VCD 质量),即使使用1.5Mbps的速率下载,也需要半个小时才能完成,这样一个漫长的等待时间实在是无法忍受。在窄带网络环境中,几乎所有基于Internet的流式媒体产品都有着类似的工作原理:首先需要开发高效的压缩编码技术,并通过一套完整有效的传输体系将其发布到用户的桌面上。目前在流式媒体领域,有三种占有主导地位的产品,它们分别是 Apple 公司的 Quick Time、Microsoft 公司的 Medi
3、a Server以及 Real公司的 Real System。本文将介绍 QuickTime 技术及其开放源代码的Darwin 流化服务器。1 QuickTime 技术介绍Apple 公司近日发布了 QuickTime 5 及 QuickTime Streaming Server 3(简称QTSS)。作为客户端的 QuickTime 5 是用于在 Internet上对高质量音频和视频内容进行创建、播放及提供数字流的软件,目前 QuickTime 在全世界的使用量已经超过 1 亿 5 千万份。QuickTime Streaming Server 3是 Apple 基于标准的、开放式源代码的流式服
4、务器软件的新版本,它包括以下新功能:跳读保护(Skip Protection),一项获得专利的特性组合,它可以保证Internet 上数字流的质量,防止中断;全新的易于使用、基于Web 的界面,用户可以在本地或远程进行管理,实现服务器配置。作为Internet 流媒体联盟(ISMA)的创建者之一,Apple 不氖褂锰uickTime 已被国际标准组织(ISO)选为 MPEG-4 的基本文件格式,可预见 Apple 将有更多 MPEG-4 产品和技术的推出。QuickTime 正迅速成为世界领先的跨平台多媒体技术,而且是迄今为止唯一的开放式源代码、基于标准的数字流解决方案。ZDNet 在 200
5、0年 9 月对于三种流式媒体服务器的特征比较说明了QTSS不仅仅被技术开发者关注,而且可以通过简单的定制成为成熟强大的产品,评测结果可见表1。表 1 ZDNet 对三类产品的评测结果服务器模块 QTSS 2.01 Media Server 7 RealServer Basic 7操作系统支持Windows NT,2000;FreeBSD;Linux;Mac OS;SolarisWindows NT,2000 Windows NT,2000并发流个数 2,000 2,000 25 free/3000 pro现场直播和广播Yes Yes Yes在线广告支持Yes Yes Yes名师资料总结-精品资
6、料欢迎下载-名师精心整理-第 1 页,共 25 页 -PPV/流加密 No/No Yes/Yes Yes/Yes分配流能力 No Yes YesSMIL 标准支持 Yes No YesRTSP标准支持 Yes No Yes多播支持Yes Yes Yes状态报告Yes Yes Yes服务器日志 Yes Yes Yes防火墙和代理支持Yes Yes Yes远程监控Yes Yes Yes客户可以使用 QuickTime Player 或其他支持 QuickTime 的应用程序在 Windows或 Macintosh 平台上接收视频流,而且QuickTime Player可以从苹果公司的网站上下载免费
7、使用。如果安装了 QuickTime 的插件,客户还可以直接通过浏览器收看。客户希望点播一个节目时,QuickTime Player 或插件将向 QTSS发送请求,指明要点播的节目名。如果该节目存在,QTSS将向客户发送相应的视频流。当客户希望收看现场直播(或实时广播)时,它首先从 QTSS获得关于当前频道的编码格式、地址等相关信息,然后再接受该频道的媒体流。对于那些希望在 Internet上实时流化视频或音频信息的用户,QTSS 服务器将是一个很好的选择,通过它可实现多项任务,例如:创建一个 24 小时在线的 Internet 广播电台;现场实况转播:如公司会议、体育节目等;创建远程学习站点
8、:如能够点播视频和演讲;图 1 是一个利用 QTSS服务器建立的现场直播场景。2 Darwin 流化服务器介绍Darwin Streaming Server(简称 DSS)是 QuickTime Streaming Server开放式源代码的版本,同时支持FreeBSD、Linux、Solaris、Windows NT 和 Windows 2000等多个操作系统,是当前所有同类产品中支持平台最多的一个。DSS的源代码和相关文档可从以下站点获得:http:/DSS源代码完全采用标准C+语言写成,编程风格非常优秀,每个C+类都对应着一对和类同名的.h/.cpp文件。但是由于大量采用了面向对象的概念
9、,如继承、多态等等;而且源文件和类相当多,所以不太容易讲清楚。因此,读者最好事先把代码完整的过滤一两遍,再配合本文,就能看得更清楚点。整个服务器包括多个子系统,分别存放在独立的工程内,如图2 所示。其中,最为重要的是基础功能类库(CommonUtilitiesLib)和流化服务器(StreamingServer)两个工程,前者是整个系统的通用代码工具箱,包括了线程管理、数据结构、网络和文本分析等多个功能模块。DSS和其他相关的工具使用基础功能类库工程中定义的功能类实现以下三个目标:(1)抽象出系统中相同或类似的功能,用于降低代码的冗余度;(2)封装基本功能,简化高层编码的复杂度;(3)隔离开操
10、作系统平台相关的代码。而流化服务器工程中包含了DSS 对多个国际标准的实现,是整个服务器的主工名师资料总结-精品资料欢迎下载-名师精心整理-第 2 页,共 25 页 -程。在本文中,我们将重点分析这两个工程中的核心代码和模块。另外,我们还将简单介绍利用 DSS 提供的开发接口(Module)扩展和定制服务器的方法。DSS实现了四种 IETF 制定的国际标准,分别是:实时流传输协议RTSP(Real-time Streaming Protocol,RFC 2326)、实时传输协议(RTP Real-time Transfer Protocol,RFC 1889)、实时传输控制协议 RTCP(Re
11、al-time Transport Control Protocol,RFC 1889)、会话描述协议 SDP(Session Description Protocol,RFC 2327)。这四个标准是开发所有流式媒体产品都必须掌握的,因此在对相关代码进行分析和二次开发之前,希望读者了解上述四种协议的基本思想,上述协议样本可从以下网站获得:http:/www.ietf.org3 基础功能类库(Common Utilities)3.1 OS 类Darwin Streaming Server支持包括 Windows,Linux 以及 Solaris 在内的多种操作系统平台。我们知道,Windows
12、 和 Unix(或 Unix-like)操作系统之间无论从内核还是编程接口上都有着本质的区别,即使是 Linux 和 Solaris,在编程接口上也大为不同。为此,DSS开发了多个用于处理时间、临界区、信号量、事件、互斥量和线程等操作系统相关的类,这些类为上层提供了统一的使用接口,但在内部却需要针对不同的操作系统采用不同的方法实现。表2 罗列出了 DSS中的主要OS 类和数据结构。表 2 DSS中的主要 OS 类和数据结构类(数据结构)名主要功能OS 平台相关的功能类,如内存分配、时间等OSCond 状态变量的基本功能和操作OSMutex 互斥量的基本功能和操作OSThread 线程类OSFi
13、leSource 简单文件类OSQueue 队列类OSHashTable 哈希表类OSHeap 堆类OSRef 参考引用类3.1.1 OSMutex/OSCond Class在有多个线程并发运行的环境中,能同步不同线程的活动是很重要的,DSS 开发了 OSMutex和 OSCond两个类用以封装不同操作系统对线程同步支持的差异。我们首先分析 OSMutex 类,这个类定义了广义互斥量的基本操作,类定义如下:class OSMutex1 public:2 OSMutex();/构造函数3 OSMutex();/析构函数4 inline void Lock();/加锁名师资料总结-精品资料欢迎下载
14、-名师精心整理-第 3 页,共 25 页 -5 inline void Unlock();/解锁6 inline Bool16 TryLock();/异步锁,无论是否成功立即返回7 private:8#ifdef _Win32_9 CRITICAL_SECTION fMutex;/临界区10 DWORD fHolder;/拥有临界区的线程id11 UInt32 fHolderCount;/进入临界区线程数/其他略 在 Windows 平台上,OSMutex 类是通过临界区(CRITICAL_SECTION)来实现的,第 10 行定义了临界区变量fMutex。类实例化时构造函数调用Initial
15、izeCriticalSection(&fMutex)初始化临界区变量,对应的在析构函数中调用DeleteCriticalSection(&fMutex)清除。Lock()函数用于对互斥量加锁,它调用私有方法RecursiveLock 实现:void OSMutex:RecursiveLock()/当前线程已经拥有互斥量,只需增加引用计数1 if(OSThread:GetCurrentThreadID()=fHolder)2 3 fHolderCount+;/增加引用计数4 return;5 6#ifdef _Win32_7:EnterCriticalSection(&fMutex);/申请进
16、入临界区8#else9(void)pthread_mutex_lock(&fMutex);10#endif11 Assert(fHolder=0);12 fHolder=OSThread:GetCurrentThreadID();/更新临界区拥有者标志13 fHolderCount+;14 Assert(fHolderCount=1);第 1 行检测如果当前线程已经拥有互斥量,就只需将内部计数fHolderCount加 1,以便纪录正在使用互斥量的方法数。如果当前线程还没有得到互斥量,第7 行调用 EnterCriticalSection()函数申请进入临界区;如果当前已经有其他线程进入临界区
17、,该函数就会阻塞,使得当前线程进入睡眠状态,直到占用临界区的线程调用 LeaveCriticalSection(&fMutex)离开临界区后才可能被唤醒。一旦线程进入临界区后,它将首先更新临界区持有者标志(第12 行),同时将临界区引用计数加 1。注意到另外一个函数TryLock(),该函数也是用于为互斥量加锁,但与 Lock()不同的是,TryLock()函数为用户提供了异步调用互斥量的功能,这是因为它调用:TryEnterCriticalSection(&fMutex)函数申请进入缓冲区:如果临界区没有被任何线程拥有,该函数将临界区的访问区给予调用的线程,并返回TRUE,否则它名师资料总结
18、-精品资料欢迎下载-名师精心整理-第 4 页,共 25 页 -将立刻返回 FALSE。TryEnterCriticalSection()和 EnterCriticalSection()函数的本质区别在于前者从不挂起线程。接着分析 OSCond类,该类定义了状态变量(Condition Variable)的基本操作,类定义如下:class OSCond 1 public:2 OSCond();/构造函数3 OSCond();/析构函数4 inline void Signal();/传信函数5 inline void Wait(OSMutex*inMutex,SInt32 inTimeoutInM
19、ilSecs=0);/等待传信函数6 inline void Broadcast();/广播传信函数7 private:8#ifdef _Win32_9 HANDLE fCondition;/事件句柄10 UInt32 fWaitCount;/等待传信用户数/其他略 虽然同是用于线程同步,但 OSCond类与 OSMutex 大不相同,后者用来控制对关键数据的访问,而前者则通过发信号表示某一操作已经完成。在Windows平台中,OSCond是通过事件(event)来实现的;构造函数调用CreateEvent()函数初始化事件句柄fCondition,而析构函数则调用CloseHandle()关
20、闭句柄。OSCond的使用流程是这样的:线程调用Wait(OSMutex*inMutex,SInt32 inTimeoutInMilSecs=0)函数等待某个事件的发生,其中 inTimeoutInMilSecs 是最长等待时间,0 代表无限长。Wait()函数内部调用了 WaitForSingleObject(fCondition,theTimeout)函数,该函数告诉系统线程在等待由事件句柄fCondition标识的内核对象变为有信号,参数theTimeout告诉系统线程最长愿意等待多少毫秒。如果指定的内核对象在规定时间内没有变为有信号,系统就会唤醒该线程,让它继续执行。而函数 Signa
21、l()正是用来使事件句柄fCondition 有信号的。Signal()函数内部实现很简单,只是简单调用SetEvent函数将事件句柄设置为有信号状态。使用 OSCond的过程中存在一种需求,就是希望通知所有正在等待的用户事件已经完成,而 Signal()函数每次只能通知一个用户,因此又开发了另外一个广播传信函数如下:inline void OSCond:Broadcast()/提示:本函数相当循环调用Signal()函数1#ifdef _Win32_2 UInt32 waitCount=fWaitCount;/等待传信的用户数3 for(UInt32 x=0;x fRunning=true)
22、,当 Entry()函数运行完后再设为非运行状态;在运行过程中,用户可以通过StopAndWaitForThread()、join()、Detach()以及 ThrowStopRequest()等函数改变线程其他状态变量。3.1.3 OSHashTable/OSQueue/OSHeap/OSRef ClassDSS定义了几个通用的较为复杂的数据结构,它们都以类的方式封装。这些数据结构不但贯穿于 DSS 的所有源代码,而且由于其封装的十分好,读者可以在看懂源代码的基础上很容易的将它们从DSS的工程中抽取出来,构建自己的基础类库,为将来的开发工作打下良好的基础。另外,对这些基础数据结构源代码的研究
23、将提高我们对于面向对象技术的掌握和领会。最主要的数据结构有四种:哈希表(OSHashTable)、队列(OSQueue)、堆(OSHeap)和对象引用表(OSRef)。前三种是我们在编程中大量使用的数据结构,而对象引用表则是类似于COM/DCOM 组件编程中 IUNKOWN 接口功能的数据结构,它首先为每个对象建立了一个字符串形式的ID,以便于通过这个 ID 找到对象(类似于 QueryInterface);另外 OSRef 类还为每个对象实例建立了引用计数,只有一个对象不再被任何人引用,才可能被释放(类似于AddRef和 Release)。鉴于这几个类在结构上有相似之处,下面我们将分析OSH
24、ashTable的源代码,以便能够帮助读者更好的理解其他几个类。OSHashTable的代码如下:templateclass OSHashTable/*提示:OSHashTable被设计成为一个类模版,两个输入参数分别为:class T:实际的对象类;class K:用于为 class T计算哈希表键值的功能类。*/1 public:2 OSHashTable(UInt32 size)/构造函数,入参是哈希表中对象的最大个数3 4 fHashTable=new(T*size);/申请分配 size个哈希对象 class T的空间5 Assert(fHashTable);6 memset(fHa
25、shTable,0,sizeof(T*)*size);/初始化7 fSize=size;/*下面的代码决定用哪种方式为哈希表的键值计算索引;如果哈希表的大小不是2 的幂,只好采用对fSize求余的方法;否则可以直接用掩码的方式,这种方式相对速度更快*/8 fMask=fSize-1;9 if(fMask&fSize)!=0)/fSize 不是 2 的幂10 fMask=0;名师资料总结-精品资料欢迎下载-名师精心整理-第 7 页,共 25 页 -11 fNumEntries=0;/当前对象数12 13 OSHashTable()/析构函数14 15 delete fHashTable;/释放空
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年Apple公司Darwin流式服务器源代码分析借 2022 Apple 公司 Darwin 服务器 源代码 分析
限制150内