webrtc 實時視頻 .net websocket信令服務器

這篇文章主要參考了 Webrtc WebSocket實現音視頻通信,很是感謝提供代碼javascript

前端部分徹底是從這篇文章複製過來的,只是修改了webscket的url,還有加入了webrtc-adapterjs ,至於作什麼,能夠點擊連接進行了解html

 

前端代碼部分(主要來自開頭說起的博文)前端

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        Welcome<br/><input id="text" type="text" />
        <button onclick="send()">發送消息</button>
        <hr/>
        <button onclick="closeWebSocket()">關閉WebSocket鏈接</button>
        <hr/>
        <div id="message"></div>

        <video id="vid1" width="320" height="240" autoplay></video>
        <video id="vid2" width="320" height="240" autoplay></video><br>
        <a id="create" href="webrtc.html#true" onclick="init()">點擊此連接新建聊天室</a><br>
        <p id="tips" style="background-color:red">請在其餘瀏覽器中打開:http://此電腦 加入此視頻聊天</p>

        <script type="text/javascript" src="http://cdn.staticfile.org/webrtc-adapter/zv4.1.1/adapter.min.js"></script>
        <script type="text/javascript">
            navigator.getUserMedia = navigator.getUserMedia ||
                navigator.webkitGetUserMedia ||
                navigator.mozGetUserMedia;

            var isCaller = window.location.href.split('#')[1];
            var websocket = null;
            //判斷當前瀏覽器是否支持WebSocket
            if('WebSocket' in window) {
                websocket = new WebSocket("ws://192.168.31.175:8181");
            } else {
                alert('當前瀏覽器 Not support websocket')
            }

            //鏈接發生錯誤的回調方法
            websocket.onerror = function() {
                setMessageInnerHTML("WebSocket鏈接發生錯誤");
            };

            //鏈接成功創建的回調方法
            websocket.onopen = function() {
                setMessageInnerHTML("WebSocket鏈接成功");
            }

            // 建立PeerConnection實例 (參數爲null則沒有iceserver,即便沒有stunserver和turnserver,仍可在局域網下通信)
            var pc = new window.RTCPeerConnection(null);

            // 發送ICE候選到其餘客戶端
            pc.onicecandidate = function(event) {
                setMessageInnerHTML("我看看 1");
                if(event.candidate !== null) {
                    setMessageInnerHTML("我看看 2");
                    websocket.send(JSON.stringify({
                        "event": "_ice_candidate",
                        "data": {
                            "candidate": event.candidate
                        }
                    }));
                }
            };

            //接收到消息的回調方法
            websocket.onmessage = function(event) {
                setMessageInnerHTML("接收到的信息");
                setMessageInnerHTML(event.data);
                if(event.data == "new user") {
                    console.log("new user");
                    location.reload();
                } else {
                    var json = JSON.parse(event.data);
                    console.log('onmessage: ', json);
                    //若是是一個ICE的候選,則將其加入到PeerConnection中,不然設定對方的session描述爲傳遞過來的描述
                    if(json.event === "_ice_candidate") {
                        pc.addIceCandidate(new RTCIceCandidate(json.data.candidate));
                    } else {
                        pc.setRemoteDescription(new RTCSessionDescription(json.data.sdp));
                        // 若是是一個offer,那麼須要回覆一個answer
                        if(json.event === "_offer") {
                            pc.createAnswer(sendAnswerFn, function(error) {
                                console.log('Failure callback: ' + error);
                            });
                        }
                    }
                }
            }

            //鏈接關閉的回調方法
            websocket.onclose = function() {
                setMessageInnerHTML("WebSocket鏈接關閉");
            }

            //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket鏈接,防止鏈接還沒斷開就關閉窗口,server端會拋異常。
            window.onbeforeunload = function() {
                closeWebSocket();
            }

            //將消息顯示在網頁上
            function setMessageInnerHTML(innerHTML) {
                document.getElementById('message').innerHTML += innerHTML + '<br/>';
            }

            //關閉WebSocket鏈接
            function closeWebSocket() {
                websocket.close();
            }

            //發送消息
            function send() {
                var message = document.getElementById('text').value;
                websocket.send(message);
            }

            // stun和turn服務器
            var iceServer = {
                "iceServers": [{
                    "url": "stun:stunserver.org"
                }, {
                    "url": "turn:numb.viagenie.ca",
                    "username": "webrtc@live.com",
                    "credential": "muazkh"
                }]
            };

            // 若是檢測到媒體流鏈接到本地,將其綁定到一個video標籤上輸出
            pc.onaddstream = function(event) {
                document.getElementById('vid2').src = URL.createObjectURL(event.stream);
            };

            // 發送offer和answer的函數,發送本地session描述
            var sendOfferFn = function(desc) {
                    pc.setLocalDescription(desc);
                    websocket.send(JSON.stringify({
                        "event": "_offer",
                        "data": {
                            "sdp": desc
                        }
                    }));
                },
                sendAnswerFn = function(desc) {
                    pc.setLocalDescription(desc);
                    websocket.send(JSON.stringify({
                        "event": "_answer",
                        "data": {
                            "sdp": desc
                        }
                    }));
                };

            // 獲取本地音頻和視頻流
            navigator.getUserMedia({
                    "audio": true,
                    "video": true
                },
                function(stream) {
                    //綁定本地媒體流到video標籤用於輸出
                    document.getElementById('vid1').src = URL.createObjectURL(stream);
                    document.getElementById('vid1').muted = true;
                    //向PeerConnection中加入須要發送的流
                    pc.addStream(stream);
                    //若是是發起方則發送一個offer信令
                    if(isCaller) {
                        pc.createOffer(sendOfferFn, function(error) {
                            console.log('Failure callback: ' + error);
                        });
                    }
                },
                function(error) {
                    //處理媒體流建立失敗錯誤
                    console.log('getUserMedia error: ' + error);
                });

            window.onload = function() {
                if(isCaller == null || isCaller == undefined) {
                    var tips = document.getElementById("tips");
                    tips.remove();
                } else {
                    var create = document.getElementById("create");
                    create.remove();
                }
            };

            function init() {
                location.reload();
            }
        </script>

    </body>

</html>
View Code

 

說起博文的java部分,我用了.net 控制檯程序簡單實現了一個,至關於一個極簡的信令服務器吧(Fleck 能夠在vs的管理nuget程序包中得到)java

static void Main(string[] args)
        {
            //客戶端url以及其對應的Socket對象字典
            IDictionary<string, IWebSocketConnection> dic_Sockets = new Dictionary<string, IWebSocketConnection>();


            var server = new WebSocketServer("ws://192.168.31.175:8181");

            //出錯後重啓
            server.RestartAfterListenError = true;

            server.Start(socket =>
            {
                socket.OnOpen = () => {
                    //獲取客戶端網頁的url
                    string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                    dic_Sockets.Add(clientUrl, socket);
                    Console.WriteLine(DateTime.Now.ToString() + "|服務器:和客戶端網頁:" + clientUrl + " 創建WebSock鏈接!");
                    
                };
                socket.OnClose = () =>  //鏈接關閉事件
                {
                    string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                    //若是存在這個客戶端,那麼對這個socket進行移除
                    if (dic_Sockets.ContainsKey(clientUrl))
                    {
                        //注:Fleck中有釋放
                        //關閉對象鏈接 
                        //if (dic_Sockets[clientUrl] != null)
                        //{
                        //dic_Sockets[clientUrl].Close();
                        //}
                        dic_Sockets.Remove(clientUrl);
                    }
                    Console.WriteLine(DateTime.Now.ToString() + "|服務器:和客戶端網頁:" + clientUrl + " 斷開WebSock鏈接!");
                };
                socket.OnMessage = message =>  //接受客戶端網頁消息事件
                {
                    string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                    foreach (var item in dic_Sockets.Where(a=>a.Key!=clientUrl))
                    {
                        item.Value.Send(message);
                    }
                    //Console.WriteLine(DateTime.Now.ToString() + "|服務器:【收到】來客戶端網頁:" + clientUrl + "的信息:\n" + message);
                };
                socket.OnBinary = b => {
                  
                };
            });

            Console.ReadKey();
        }
View Code

 

記錄完畢,這個東西僅僅只是個demo,能夠拿來玩一下web

相關文章
相關標籤/搜索