【Javascript】【WebRTC】WebRTC从原理到实现(八):客户端代码

let state = -1;
let roomid = "10086";
let peerId;
let peerName;
let peerConnection;
let socket;

//信令服务器
const signalServer = "ws://120.197.7.239:1991";
//ICE服务器
const iceServer = {
    "iceServers": [
        {
            "urls": "stun:120.79.34.78:3478"
        },
        {
            credential: "test",
            username: "test",
            urls: [
                "turn:120.79.34.78:3478?transport=udp",
                "turn:120.79.34.78:3478?transport=tcp"
            ]
        }
    ]
};

document.onreadystatechange = () => {
    if (document.readyState != "complete")
        return;
    document.getElementById("bt_01").onclick = () => {
        state = 0;
        start();
    };
    document.getElementById("bt_02").onclick = () => {
        state = 1;
        start();
    };
};

//客户端启动
function start() {
    navigator.mediaDevices.getUserMedia({
        video: true,
        audio: true
    }).then(stream => {
        console.info("==========> add local stream");
        //移除本地音频轨道
        let tracks = stream.getTracks();
        stream.removeTrack(tracks[0]);
        //显示本地媒体流
        document.getElementById("v_01").setAttribute("src", window.URL.createObjectURL(stream));
    });
    navigator.mediaDevices.getUserMedia({
        video: true,
        audio: true
    }).then(stream => {
        //判断浏览器是否支持WebRTC
        if (testApiCompatability()) {
            //连接媒体服务器
            connectIceServer(stream);
            //连接信令服务器
            connectSignalServer();
        }
        else
            alert("当前浏览器不支持WebRTC");
    });
}

//判断浏览器是否支持WebRTC
function testApiCompatability() {
    window.RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
    window.RTCSessionDescription = window.RTCSessionDescription || window.webkitRTCSessionDescription || window.mozRTCSessionDescription;
    window.RTCIceCandidate = window.RTCIceCandidate || window.webkitRTCIceCandidate || window.mozRTCIceCandidate;
    return !!window.RTCPeerConnection;
}

//连接媒体服务器
function connectIceServer(stream) {
    console.info("==========> connect ice server");
    peerConnection = new RTCPeerConnection(iceServer);
    console.info("==========> add local stream to peer connection");
    peerConnection.addStream(stream);
    //添加远程流成功
    peerConnection.onaddstream = event => {
        console.info("==========> add remote stream to peer connection");
        document.getElementById("v_02").setAttribute("src", window.URL.createObjectURL(event.stream));
    };
    //ICE服务器生成本地candidate
    peerConnection.onicecandidate = event => {
        if (!event.candidate)
            return;
        console.info("==========> collect self candidate");
        sendMessage(socket, {
            type: "candidate",
            state: state,
            peerid: peerId,
            name: peerName,
            candidate: JSON.stringify(event.candidate)
        });
    }
    //连接状态改变
    peerConnection.oniceconnectionstatechange = event => {
        console.info("==========> ice connection state change: " + event.target.iceConnectionState);
        if (event.target.iceConnectionState == "failed") {
            socket.close();
            alert("ice connection fail");
        }
        if (event.target.iceConnectionState == "disconnected") {
            socket.close();
            alert("ice connection disconnect");
        }
        if (event.target.iceConnectionState == "completed")
            alert("ice connection succeed");
    }
}

//连接信令服务器
function connectSignalServer() {
    socket = new WebSocket(signalServer);
    //socket连接成功
    socket.onopen = function () {
        console.info("==========> connect signal server");
        peerId = "CLIENT-" + new Date().getTime();
        peerName = peerId;
        if (state == 0)
            socket.target = "aodun5";
        //发送connect消息
        console.info("==========> send connect");
        let msg = {
            type: "connect",
            state: state,
            roomid: roomid,
            peerid: peerId,
            name: peerName
        }
        sendMessage(socket, msg);
    };
    //socket连接断开
    socket.onclose = function (code) {
        console.info("==========> socket disconnect");
    }
    //socket连接失败
    socket.onerror = (socket, event) => {
        alert("socket connect fail");
    }
    //消息监听
    socket.onmessage = message => {
        let data = JSON.parse(message.data);
        switch (data.type) {
            //发送offer
            case "onconnect":
                console.info("==========> get onconnect");
                if (state == 0)
                    sendOffer();
                break;

            //发送answer
            case "onoffer":
                sendAnswer(data.offer);
                break;

            //收到answer
            case "onanswer":
                onAnswer(data.answer);
                break;

            //收到candidate
            case "oncandidate":
                onCandidate(data.candidate);
                break;
        }
    }
}


//发送offer
function sendOffer() {
    peerConnection.createOffer().then(offer => {
        console.info("==========> send offer");
        peerConnection.setLocalDescription(offer);
        let msg = {
            type: "offer",
            state: state,
            roomid: roomid,
            peerid: peerId,
            name: peerName,
            offer: JSON.stringify(offer)
        };
        sendMessage(socket, msg);
    });
};

//发送answer
function sendAnswer(offer) {
    console.info("==========> send answer");
    peerConnection.setRemoteDescription(new RTCSessionDescription(JSON.parse(offer))).then(() => {
        peerConnection.createAnswer().then(answer => {
            peerConnection.setLocalDescription(answer);
            let msg = {
                state: state,
                type: "answer",
                peerid: peerId,
                name: peerName,
                answer: JSON.stringify(answer)
            };
            sendMessage(socket, msg);
        });
    });
}

//收到answer
function onAnswer(answer) {
    console.info("==========> get answer");
    peerConnection.setRemoteDescription(new RTCSessionDescription(JSON.parse(answer)));
}

//增加候选,添加网络信息
function onCandidate(candidate) {
    console.info("==========> get candidate");
    peerConnection.addIceCandidate(new RTCIceCandidate(JSON.parse(candidate)));
}

//向信令发送消息
function sendMessage(socket, message) {
    socket.send(JSON.stringify(message));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值