WebRTC 学习笔记 创建信令服务器和连接客户端

信令服务器

使用node.js作为服务器

var WebSocketServer = require("ws").Server,
    wss = new WebSocketServer({port:8888}),
    /*存储所有的连接用户*/
    users = {};
/*监听客户端发起的连接*/
wss.on("connection",function (connection) {
    console.log("User connected");
    /*监听客户端的消息*/
    connection.on("message",function (message) {
        var data;
        /*保证只接受JSON格式的消息*/
        try{
            data = JSON.parse(message);
        }catch (e) {
            console.log("Error parsing JSON");
            data = {};
        }
        switch (data.type) {
            case "login":
                console.log("User logged in as ",data.name);
                if (users[data.name]){
                    sendTo(connection,
                        {
                            type:"login",
                            success:false
                        })
                }else {
                    users[data.name] = connection;
                    connection.name = data.name;
                    sendTo(connection,
                        {
                            type:"login",
                            success:true
                        });
                }
                break;
            case "offer":
                /*data.name为客户端想要把offer发送给的人*/
                console.log("Sending offer to",data.name);
                /*conn为offer发往的人.connection为发送offer的人*/
                var conn = users[data.name];
                if (conn != null){
                    connection.otherName = data.name;
                    sendTo(conn,{
                        type:"offer",
                        offer:data.offer,
                        name:connection.name
                    });
                }
                break;
            case "answer":
                console.log("Sending answer to ",data.name);
                var conn = users[data.name];
                if (conn != null){
                    connection.otherName = data.name;
                    sendTo(conn,{
                        type:"answer",
                        answer:data.answer
                    });
                }
                break;
            case "candidate":
                console.log("have a candidate from ",connection.name);
                console.log("Sending candidate to ",data.name);
                var conn = users[data.name];
                if (conn != null){
                    sendTo(conn,{
                        type: "candidate",
                        candidate: data.candidate
                    });
                }
                break;
            case "leave":
                console.log("Disconnecting user from ",data.name);
                var conn = users[data.name];
                conn.otherName = null;
                if (conn != null){
                    sendTo(conn,{type:"leave"});
                }
                break;
            default:
                sendTo(connection,
                    {
                        type:"error",
                        message:"Unrecognized command:" + data.type
                    });
                break;
        }
    });
    connection.on("close",function () {
        if (connection.name){
            delete users[connection.name];
            if (connection.otherName){
                console.log("Disconnecting user from ",connection.otherName);
                var conn = users[connection.otherName];
                conn.otherName = null;
                if (conn != null){
                    sendTo(conn,{type:"leave"});
                }
            }
        }
    })
});
wss.on("listening",function () {
    console.log("Server start...");
})
function sendTo(conn,message) {
    conn.send(JSON.stringify(message));
}


客户端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>web_rtc_3</title>
    <style>
        body{
            background-color: #3D6DF2;
            margin-top: 15px;
            font-family: sans-serif;
            color: white;
        }
        video{
            background-color: black;
            border: 1px solid gray;
        }
        .page{
            position: relative;
            display: block;
            margin: 0 auto;
            width: 500px;
            height: 500px;
        }
        #yours{
            width: 150px;
            height: 150px;
            position: absolute;
            top: 15px;
            right: 15px;
        }
        #theirs{
            width: 500px;
            height: 500px;
        }
    </style>
</head>
<body>
    <div id="login-page" class="page">
        <h2>Login As</h2>
        <input type="text" id="username">
        <button id="login">Login</button>
    </div>
    <div id="call-page" class="page">
        <video id="yours" autoplay></video>
        <video id="theirs" autoplay></video>
        <input type="text" id="their-username">
        <button id="call">Call</button>
        <button id="hang-up">Hang Up</button>
    </div>
    <script>
        /*name:本用户的名称,connectedUser:要连接的用户的名称*/
        var name,connectedUser;
        /*与服务器进行连接*/
        var connection = new WebSocket('ws://localhost:8888');
        var loginPage = document.querySelector('#login-page'),
            usernameInput = document.querySelector('#username'),
            loginButton = document.querySelector('#login'),
            callPage = document.querySelector('#call-page'),
            theirUsernameInput = document.querySelector('#their-username'),
            callButton = document.querySelector('#call'),
            hangUPButton = document.querySelector('#hang-up');
        var yourVideo = document.querySelector('#yours'),
            theirVideo = document.querySelector('#theirs'),
            /*yourConnection:当前页面的RTCPeerConnection*/
            yourConnection,stream;
        callPage.style.display = "none";
        /*与服务器进行连接后的函数*/
        connection.onopen = function () {
            console.log("Connected");
        };
        /*从服务器返回数据的函数*/
        connection.onmessage = function (message) {
            console.log("Got message",message.data);
            var data = JSON.parse(message.data);
            switch (data.type) {
                case "login":
                    onLogin(data.success);
                    break;
                case "offer":
                    onOffer(data.offer,data.name);
                    break;
                case "answer":
                    onAnswer(data.answer);
                    break;
                case "candidate":
                    onCandidate(data.candidate);
                    break;
                case "leave":
                    onLeave();
                    break;
                default:
                    break    ;
            }
        };
        /*从服务器发生错误的函数*/
        connection.onerror = function (error) {
            console.log("Got error",error);
        };
        /*单击登陆按钮,向服务器发送login类型数据*/
        loginButton.addEventListener("click",function (event) {
            name = usernameInput.value;
            if (name.length > 0){
                send({
                    type:"login",
                    name:name
                });
            }
        });
        /*触发onLogin函数*/
        function onLogin(success) {
            if (success === false){
                alert("Login unsuccessful, please try a different name.");
            }else {
                loginPage.style.display = "none";
                callPage.style.display = "block";
                startConnection();
            }
        };
        function startConnection() {
            if (hasUserMedia()){
                navigator.getUserMedia(
                    {video:true,audio:false},
                    function (myStream) {
                        stream = myStream;
                        /*将自己的摄像头在自己的部分显示*/
                        yourVideo.srcObject = stream;
                        if (hasRTCPeerConnection()){
                            setupPeerConnection(stream);
                        }else {
                            alert("Sorry, your browser does not support WebRTC.");
                        }
                    },
                    function (error) {
                        console.log(error)
                    }
                );
            }else {
                alert("Sorry, your browser does not support WebRTC.");
            }
        };
        function setupPeerConnection(stream) {
            var configuration = {};
            /*创建RTCPeerConnection*/
            yourConnection = new RTCPeerConnection(configuration);
            yourConnection.addStream(stream);
            /*由setRemoteDescription触发*/
            yourConnection.onaddstream = function (e) {
                theirVideo.srcObject = e.stream;
            };
            yourConnection.onicecandidate = function (event) {
                if (event.candidate){
                    send({
                        type: "candidate",
                        candidate: event.candidate
                    });
                }
            };
        };
        /*开始于另一个用户连接*/
        callButton.addEventListener("click",function () {
            var theirUsername = theirUsernameInput.value;
            if (theirUsername.length > 0){
                startPeerConnection(theirUsername);
            }
        });
        /*向另一个端发送offer*/
        function startPeerConnection(user){
            connectedUser =  user;
            /*开始创建offer*/
            yourConnection.createOffer().then(function (offer) {
                send({
                    type:"offer",
                    offer:offer
                });
                yourConnection.setLocalDescription(offer);
            },function (error) {
                alert("An error has occurred while create offer.");
            });
        };
        /*收到另一端的offer,返回一个answer*/
        function onOffer(offer,name) {
            connectedUser = name;
            yourConnection.setRemoteDescription(new RTCSessionDescription(offer));
            yourConnection.createAnswer().then(function (answer) {
                yourConnection.setLocalDescription(answer);
                send({
                    type: "answer",
                    answer: answer
                });
            },function (error) {
                alert("An error has occurred while create answer.");
            })
        };
        /*收到answer*/
        function onAnswer(answer) {
            yourConnection.setRemoteDescription(new RTCSessionDescription(answer));
        };
        hangUPButton.addEventListener("click",function () {
            send({
                type:"leave"
            });
            onLeave();
        });
        function onLeave() {
            connectedUser =null;
            theirVideo.srcObject = null;
            yourConnection.close();
            yourConnection.onicecandidate = null;
            yourConnection.onaddstream = null;
            setupPeerConnection(stream);
        };
        function send(message) {
            if (connectedUser){
                message.name = connectedUser;
            }
            connection.send(JSON.stringify(message));
        };
        function onCandidate(candidate) {
            yourConnection.addIceCandidate(new RTCIceCandidate(candidate));
        };
        function hasUserMedia() {
            return !!navigator.getUserMedia;
        };
        function hasRTCPeerConnection() {
            return !!window.RTCPeerConnection;
        }



    </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值