基于Android的VoIP系統(tǒng)的設(shè)計與實現(xiàn)
2 VoIP的具體實現(xiàn)
這里將實現(xiàn)一個完整的VoIP系統(tǒng),包括協(xié)議棧的實現(xiàn)、JNI的編寫以及上層UI的設(shè)計實現(xiàn)等。
2.1 SIP協(xié)議棧及UA
SIP協(xié)議棧直接關(guān)系到整個系統(tǒng)的質(zhì)量與效率,本文將采用純C語言開發(fā)的PJSIP庫。該庫采用C語言開發(fā),且源碼開放,在兼容性與效率上有明顯優(yōu)勢,不僅體積小(完整的SIP封裝也不過150 KB),同時還實現(xiàn)了一個內(nèi)存池,使得安全系數(shù)與運行效率大為提高,該系統(tǒng)所采用的就是優(yōu)化后的PJSIP庫。
2.1.1 PJSIP協(xié)議棧
PJSIP協(xié)議棧遵循標(biāo)準(zhǔn)的SIP協(xié)議,采用分層架構(gòu):SIP/SDP消息編碼解析層、傳輸管理層、SIP終端、事務(wù)層、會話層以及應(yīng)用層等。由于SIP協(xié)議采用文本消息發(fā)送請求和響應(yīng),所以首先需要將SIP消息按照巴斯克范式(ABNF)編碼和解析,這就是SIP/SDP消息編碼解析層所完成的功能。傳輸管理層用來管理用戶代理與服務(wù)器之間的請求和相應(yīng);SIP終端是PJSIP中轉(zhuǎn)機制的實現(xiàn),它主要負責(zé)管理各個SIP組建,例如像SIP終端實例注冊組件,分發(fā)消息到事務(wù)層、會話層及應(yīng)用層,回傳處理結(jié)果,管理定時器、I/O隊列等;事務(wù)層通過狀態(tài)機機制管理SIP信令,每一次狀態(tài)機狀態(tài)的改變都將觸發(fā)回調(diào)函數(shù);會話層負責(zé)會話的發(fā)起與響應(yīng),一般與應(yīng)用層結(jié)合在一起,用于用戶交互,不同的平臺有不同的實現(xiàn),本文使用Andriod的GUI來實現(xiàn)。
PJSIP是一個高度封裝的庫,實際上它是通過PJSUA子庫來實現(xiàn)應(yīng)用的。一個完整的PJSUA生命周期,首先需要初始化,通過函數(shù)init()來實現(xiàn)。在這個函數(shù)中,將創(chuàng)建代理、初始化變量和堆棧,以及創(chuàng)建一個UDP傳輸并在最后啟動代理;第二步將為UA添加用戶,如果需要的話,還要向服務(wù)器注冊用戶;當(dāng)用戶添加成功后,此時可以建立一個呼叫連接,發(fā)起會話;當(dāng)會話連接成功后,就可以使用SRTP協(xié)議實時傳輸加密后的數(shù)據(jù),進行通話。最后的過程是掛起或銷毀呼叫。
2.1.2 UA原理
UA(User Agency)是協(xié)議棧的具體實現(xiàn),PJSIP通過封裝了的PJSUA來實現(xiàn),在這一點上,大部分的SIP庫都大同小異,在此將介紹UA的工作原理。
一個典型的UA包含UAC(User Agency Client)和UAS(User Agency Server)兩部分。會話由UAC發(fā)起。當(dāng)呼叫發(fā)起時,UAC將首先發(fā)送“IN-VITE”消息給SIP代理服務(wù)器,服務(wù)器收到“INVITE”消息后將返回一個應(yīng)答“200 OK”,并回答“ACK”進行確認,同時通知主叫用戶(即會話發(fā)起用戶)上線通話。如果主叫端(用戶端)主動結(jié)束會話,UAC將返回“BYE”消息,同時通知服務(wù)器;如果用戶端收到服務(wù)器傳來的“BY-E”消息,回答“200”,并結(jié)束會話。
服務(wù)器端,UAS收到UAC(用戶端)發(fā)來的“INVITE”消息,首先從消息中提取出主、被叫對象,然后檢查當(dāng)前是否有空閑信道,若沒有則返回“486 BUSY HERE”(即系統(tǒng)忙)消息;接著將檢查被叫用戶是否在服務(wù)區(qū),如果被叫對象不在服務(wù)范圍,則返回“404 NOT FOUND”(即用戶不在服務(wù)區(qū));若被叫用戶成功上線,則返回“200 OK”,同時準(zhǔn)備開始會話。
SIP協(xié)議棧一般使用SIP統(tǒng)一資源定位符(URL)來標(biāo)識,它根據(jù)URL來尋址,如集群用戶“200”,“300”分別對應(yīng)SIP用戶為“200@192.168. 1.100”,“300@192.168.1.100”。本文中也使用這種方式來測試通信。
2.2 JNI的實現(xiàn)
PJSIP庫和Java類連接是通過JNI來實現(xiàn)的,這也是Android NDK的實現(xiàn)機制,JNI是SUN公司推出的用于Java調(diào)用其他語言的接口。
首先需要一個中間類,這個類中主要建立一些方法用于調(diào)用C/C++本地函數(shù)。它們的類型均為“publicstatic native int”,以便其他的Java類能夠調(diào)用。
2.2.1 新建PJSIP類
為各個待實現(xiàn)的類新建一個包,可以命名為“com.a(chǎn)ndroid.voip.pjsip”,在該包中添加該系統(tǒng)相關(guān)的一些類,主要有如下6個類:
這些類分別為上節(jié)中原理各個步驟的實現(xiàn)。這部分僅僅是為C庫的調(diào)用提供一個接口,因此具體的實現(xiàn)將放在本地C/C++程序中。本文引用地址:http://butianyuan.cn/article/156376.htm
評論