我們知道,基於WEBRTC實現的多對多實時音視頻互動通信就必須需要搭建信令服務器作為信令轉發操作。那么我首先了解一下,什么是webrtc信令服務器?
在webrtc的規范中,其實是沒有將信令服務這一塊納入到整個規范當中的。更多的是規范客戶端所有的過程。為什么沒有納入到規范中,這是因為各個公司的業務模型都是不一樣的。很難將每個公司的信令都並成一套規范。所以這樣,還不如讓他們自己去定義。只要是我必須的信息能交換,其他的業務,你自己去定義,這樣就比較靈活,各個公司就更容易去接受,這其實是對webrtc整個的推廣是比較有好處的。
信令服務器的作用:
如果沒有信令服務器,各個webrtc之間肯定是不能通信的。
看圖,這張圖就清晰地表達了信令服務器在整個過程的作用,首先看藍色部分,一個是發起端,一個是接收端,那么發起端和接收端之前要傳輸媒體數據的時候,他有兩個信息必須要通過信令服務器的相互交換才能實現通信的,那兩個信息是什么呢,第一個是媒體信息,這個媒體信息通過什么來表述呢,那就是SDP,這個SDP會在往后的分享會給大家作詳細的介紹,可以簡單地理解,我們雙方需要通信,那么你的編解碼器是什么,比如我現在進行視頻傳輸,我的編解碼是H264,那么對方也要告訴我你能不能支持h264,這個信息必須要傳遞的,另外你是否支持音頻,是否支持視頻,你的編碼器是什么,這些信息都是通過SDP協議描述出來,然后通過信令服務器,首先就將這個SDP發送到服務器,然后服務器再中轉,再中轉到另一端,為什么要通過信令服務器進行中轉,這是因為這時候雙方還沒有建立起連接,相互之間還不知道對方的存在。第二個要傳遞的是網絡信息,大家都知道兩個webrtc之間他們會盡可能地選擇P2P進行傳輸,那么在他們進行連接之前,要怎樣發現對方呢?那也是通過信令服務器,首先你要將你相關的網絡信息傳輸到信令服務器。那這個信令服務器就幫你交互到另外一端,那這一端拿到你的信息之后,才知道,大家都是處於同一個局域網內,那就直接通過P2P傳輸就好了,那如果是不同一個局域網內,那么就需要使用P2P穿透,所以這個信令服務器最基礎的作用就是一是媒體信息的交換,二是網絡信息的交換,再有就是第三個就是我們的具體業務,比如說是加入房間,離開房間,禁言,或者給對方權限發言等,所以這就是整個信令服務器在WEBRTC通信中的作用。
為什么要使用socket.io,其中有幾個優點
1. socket.io 是websocket超集,他身本就有websocket的功能,我們都知道在我們進行傳輸的時候,一般有兩個協議,一個是TCP協議,一個是UDP協議,底層協議里面,一般來說UDP是用於流媒體的傳輸,音頻,視頻,還有文本,文字的聊天,但UDP的問題在於,他是不可靠的,他會丟包,這個對於音頻和視頻來說是沒有問題的,當網絡狀況不好的時候,他可以丟包,我丟了一幀數據,他最多就是卡一下,但對於信令來說,他必須是需要可靠的,我們需要我們的數據發送到哪,從哪來的,這些都是需要可靠的傳輸協議作支撐,他要的是要么完全接收,要么就是完全不接收。所以對於信令來說是必須要使用tcp,而我們的websokcet是使用tcp的,所以socket.io也是使用tcp
2. socket.io有房間的概念,我們來想想,如果我們兩個人之間進行通信,我們就必須先要進行一個房間里,我們要開會也好,什么也好,首先要聚集在一起,這是一個虛擬的邏輯概念。我們看過webrtc的demo可以知道,他實際上有三種服務器,第一種是room服務器,第二種就是我們的信令服務器,第三種就是流媒體中轉服務器。而我們選用的socket.io他因為本身就具有房間這么一個概念,也具有信令轉發這么一個功能,所以我們就無需再另外搭建room服務器和信令服務器,直接使用socket.io就可以了。
3. socket.io跨平台,跨終端,跨語言:我們可以用JS,也可以用JAVA,這樣就使我們很方便地在各個終端中使用。
socket.io的工作原理
我們選擇了Nodejs中的socket.io進行講解。首先我們將npm的源換成淘寶的,這樣下載的時候會快一點
npm install -g cnpm --registry=https://registry.npm.taobao.org
接下來我們使用cnpm的方式進行安裝socket.io庫
cnpm install socket.io
使用socket.io發送消息
實際上使用socket.io發送消息是的情況有很多,有10多種,但是我們必須要了解的大概也就是4,5種。我們來一個一個看
1. 給本次連接發消息
socket.emit(),把它理解成send就可以了,當我們的客戶端發送一條消息給服務器端,服務器端收到消息之后,返一個callback,舉個栗子,就是我要加個房間,然后服務器返回一個提示,你已加入成功。我收到這個提示之后,我就進行其他的操作,這一個過程都是異步的。
2. 給某個房間內所有人發消息。
這種情況相當於一個廣播,給在房間內的所有人都發消息,包括我自己。還是以上邊的栗子說說,我加入了房間,那么給房間內的所有人發一個消息說,這個人加入進來了。當然有些業務就不需要這樣,你加入了就加入了,還有一個就是各個用戶端都需要維護一個用戶列表。那誰來誰走了,都要清楚,這個時候每個人都要收到這個消息,對於發送者來,我們就可以根據這個消息進行處理,比如音視頻的處理。對於其他用戶來說,收到了這個用戶加入來進來的消息,我就更新一下我的用戶列表。將這個用戶添加我的用戶列表里面去。
它用的是 io.in(room).emit(),這個IO,解釋一下,代表整個這個節點的socket里面的所有用戶都包含在內,in(room)就是代表節點某個房間內。也有一種寫法是io.sockets.in,但這個sockets可寫可不寫
3. 除了本連接外,給某個房間內所有人發消息。
這種就是,給某個房間內除我自己之外的人發一個消息,比如全體靜音,就是不讓人說話,只允許我自己說話
使用:
socket.to(room).emit(),to(room)
就是給某個房間內除我自己之外的人發消息
4. 除本連接外,給所有人發消息
socket.broadcast.emit()
跟第三種情況很相似,但,這個是給本人外,這個節點的所有房間發消息。
socket.IO客戶端處理消息
當我們客戶端收到的處理信息之后,怎樣處理。
1. 發送action命令
server: socket.emit(‘action’); // 當服務器發送了個action
client: socket.on(‘action’,function(){}); // 我們的客戶端就需要監聽這個動作。
2. 發送action命令,還在data數據
server : socket.emit(‘action’,data);
client: socket.on(‘action’,function(data){…});
3. 發送了action命令,還有兩個數據
server: socket.emit(action,arg1,arg2);
client: socket.on(‘action’,function(arg1,arg2){…});
4. 發送一個action命令,在emit方法中包含回調函數
server: socket.emit(‘action’,data,function(arg1,arg2){…});
client: socket.on(‘action’,function(data,fn){fn(‘a’,’b’);});
至止,關於使用socket.io搭建簡單的信令服務器的教程到這里,下一次本光頭將介紹實戰中如何應用socket.io。