最近五一回家,終於有機會能安靜的看一下流媒體這方面相關的知識,准備分析live555的源碼,接下來會把我讀源碼的過程記錄成博客,以供其他的同路人參考。
因為再讀源碼的過程中,並不是一路順着讀下來,往往是讀到后面,才能反過來明白之前讀的內容,所以有的時候會寫的有點穿越感。
在這個過程中,參考了其他大牛的博客,所以一些基本概念,就不再重復,也感謝前輩們的貢獻。
下面進入正題:
我們觀察live555MediaServer.cpp里的main函數,主要做了三件事:
1. 創建TaskScheduler和UsageEnvironment,一個用來做調度,一個代表運行的環境。
2. 創建一個DynamicRTSPServer,這個繼承自RSTPServer對象。
3. 進入死循環,實際上是使用select來完成並發網絡模型。
那這篇文章就是主要講的創建一個DynamicRTSPServer到底發生了什么(即第二條),下面這張圖是根據源碼畫出來的(能力有限,畫的簡陋),是創建一個DynamicRTSPServer過程中的重要函數調用關系:

下面挑重點講一下:
DynamicRTSPServer繼承自RTSPServer,所以構造DynamicRTSPServer也會構造其父類RTSPServer,RTSPServer構造函數如下:

其實核心代碼就是調用turnOnBackgroundReadHandling函數,這個函數的代碼如下:
![]()
再追蹤:

這下就明了了,首先用assignHandler()把一些屬性和server socket做一個綁定,其次就是使用FD_SET把這個server socket加入select的相應的集合,為接下來的select死循環做准備。
那么turnOnBackgroundReadHandling()的參數incomingConnectionHandlerRTSP又是什么鬼呢?上邊說道,這個函數指針會和當前的socket被做一個綁定,所以當這個socket接收到數據的時候就會調用這個函數(這個以后會細說)。incomingConnectionHandlerRTSP經過層層調用,來到下面這個函數:

可以看到,server socket 進行accept操作就是在這一步進行的,也就是說初始的時候集合中只有一個server socket,當有客戶端發起鏈接的時候,select調用返回,發現server socket發生了讀操作,接下來便會調用注冊了的incomingConnectionHandlerRTSP()函數,在這個函數里,依次調用accept()函數創建新的socket來與客戶端進行通信。
incomingConnectionHandlerRTSP()里接下來會調用createNewClientSession(),一個RTSPClientSession代表着一條與客戶端的鏈接。createNewClientSession()經過層層調用,會來到如下函數:

這下就全明了了,又是調用turnOnBackgroundReadHandling()函數,只不過參數從incomingConnectionHandlerRTSP函數指針變為了incomingRequestHandler,為什么呢,因為上一次我們調用這個函數是針對於server socket,server socket的主要功能是建立網絡連接並分配新的socket和客戶端進行會話。而這一次,我們是針對的socket是直接和客戶端進行通話的socket,兩種socket接收到數據時處理操作是不同的,所以綁定的函數也是不一樣的。
這次綁定這個函數的內部結構是什么樣的呢,經過調用來到如下函數:

簡單的說就是使用readsock()從socket中讀數據,使用handleRequstBytes()來對數據進行處理,比如客戶端發過來了DESCRIBE或者SETUP等要分別怎么處理呢,就是在這個函數里進行的。
