[WebRTC] 透過 WebRTC 做到P2P對談(2) – Client 連接、登入、登出篇

2017-03-02

上一篇 我們說到如何架設一台 websocket server 作為 signaling server ,今天我們來做做client 這一端,我們這篇文章要做到跟Signaling Server 聯繫,然後登入,還有登出畫面像是這樣,我盡量簡單化,不會讓過多物件去干擾,每一個事件,我都有進行記錄列出來,方便觀察
Image 049

其實首先,第一格步驟當網頁執行的時候,應該就要跟signaling server 聯繫 ,當成功時候會收到type:hello 並且列出server的message : Welcome to connet Signaling Server

//connecting to our signaling server 
//請帶入自己WS server 的ip位置
var wsConn = new WebSocket('ws://192.168.6.145:9090');

// Connection
var yourConn;

wsConn.onopen = function () {

    AddLog('Connected to the signaling server.', 'b');
};

再來建立起跟singaling server連線後,就是登入的部分

        // Person 1 Login
        $('#btnLoginPerson1').click(function () {
            name = 'PERSON1';
            send({
                type: "login",
                name: name
            });
        });

接下來看一下各狀態的處理

//when we got a message from a signaling server 
wsConn.onmessage = function (msg) {
    console.log("Got message :", msg);

    try {
        var data = JSON.parse(msg.data);

        switch (data.type) {
            case "login":
                handleLogin(data);
                break;
                //when somebody wants to call us 
            case "offer":
                AddLog(data.name + "進入了!!", 'r');
                handleOffer(data.offer, data.name);
                break;
            case "answer":
                handleAnswer(data.answer);
                break;
                //when a remote peer sends an ice candidate to us 
            case "candidate":
                handleCandidate(data.candidate);
                break;
            case "leave":
                AddLog('登出成功 ', 'b');
                handleLeave();
                break;
            case "hello":
                AddLog(data.message, 'b');
                //alert(data.message);
                break;
            default:
                break;

        }
    }
    catch (e) {
        console.log('signaling server error : ' + msg.data + " 。Exception Message :" + e);
        AddLog('signaling server error : ' + msg.data + " 。Exception Message :" + e, 'r');
    }


};

wsConn.onerror = function (err) {
    AddLog("Web Socket Connection 發生錯誤 : " + JSON.stringify(err), 'r');
};


function send(message) {
    //attach the other peer username to our messages 
    if (connectedUser) {
        message.name = connectedUser;
    }

    wsConn.send(JSON.stringify(message));
};

其中有些code 我會在下一篇說到,這一篇主要再把singaling server 建立起來,並且跟stun server 建立起自己是一個peer端
當收到type login 之後開始跟stun server 建立 ,也就是一開始先送login 資訊給signaling server ,之後signaling server 說成功 ,在client 之後去呼叫stun server 建立起自己變成一個peer connection ,所以上面的code 當type : login 收到時會呼叫 handleLogin ,下面是handleLogin 的code

//After Connected Action 
//Type:login 
//處理登入後的狀態,收到type:login的時候呼叫
function handleLogin(data) {

    if (data.success === false) {
        AddLog('[Error] : ' + data.message, 'r');
    } else {

        //********************** 
        //Starting a peer connection 
        //建立起自己為一個可Connection的端點
        //********************** 

        //using Google public stun server 
        AddLog('登入成功 :' + name, 'b');
        var configuration = {
            "iceServers": [{ "url": "stun:stun2.l.google.com:19302" }]
        };

        //  yourConn = new webkitRTCPeerConnection(configuration, { optional: [{ RtpDataChannels: true }] });
        yourConn = new webkitRTCPeerConnection(configuration);

        // Setup ice handling 
        yourConn.onicecandidate = function (event) {
            if (event.candidate) {
                AddLog('送出 candidate :' + JSON.stringify(event.candidate), 'b');
                send({
                    type: "candidate",
                    candidate: event.candidate
                });
            }
        };

        yourConn.ondatachannel = function (event) {
            var receiveChannel = event.channel;
            receiveChannel.onmessage = function (event) {
                AddLog(connectedUser + ": " + event.data, 'y');
            };
        };


        //creating data channel 
        dataChannel = yourConn.createDataChannel("channel1", { reliable: true });

        dataChannel.onerror = function (error) {
            console.log("Ooops...error:", error);
        };

        //when we receive a message from the other peer, display it on the screen 
        dataChannel.onmessage = function (event) {
            // chatArea.innerHTML += connectedUser + ": " + event.data + "<br />";
            AddLog('dataChannel.onmessage :' + connectedUser + ": " + event.data);
        };

        dataChannel.onclose = function () {
            console.log("data channel is closed");
        };

    }
};

在來就是離線呼叫的呼叫 ,就是跟 signaling server 說我要離開並且呼叫 自己本身的webrtcconnection = null

//Leave
//將 RTCPeerConnection 關閉
function handleLeave() {
    connectedUser = null;
    yourConn.close();
    yourConn.onicecandidate = null;
    name = '';
    connectedUser = '';
};

執行結果 :
Server:
2017-03-02 16_24_01 的螢幕擷圖

client:
2017-03-02 16_21_52 的螢幕擷圖

參考資料:
https://www.tutorialspoint.com/webrtc/webrtc_text_demo.htm

source code:
https://github.com/donma/SimepleWebRTCText


當麻許的超技八 2014 | Donma Hsu Design.