跨平臺、高性能的媒體轉發服務器實現

最近實現了一個媒體轉發服務器,代碼可以編譯成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++語言開發。

本文所討論的服務器在實現後已經部署在實際環境使用,效果良好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章