Nodejs搭建音视频通信 信令服务器

Posted wangle100

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nodejs搭建音视频通信 信令服务器相关的知识,希望对你有一定的参考价值。

1、安装nodejs  node-v10.16.3-x64.msi

2、安装配置环境变量

  这里的环境配置主要配置的是npm安装的全局模块所在的路径,以及缓存cache的路径,之所以要配置,是因为以后在执行类似:npm install express [-g] (后面的可选参数-g,g代表global全局安装的意思)的安装语句时,会将安装的模块安装到【C:\\Users\\用户名\\AppData\\Roaming\\npm】路径中,占C盘空间。例如:我希望将全模块所在路径和缓存路径放在我node.js安装的文件夹中,则在我安装的文件夹【D:\\Develop\\nodejs】下创建两个文件夹【node_global】及【node_cache】。

  创建完这两个空文件夹之后,打开cmd命令窗口,输入:

  npm config set prefix "D:\\Develop\\nodejs\\node_global"

       npm config set cache "D:\\Develop\\nodejs\\node_cache"

 

 

  接下来设置环境变量,关闭cmd窗口,“我的电脑”-右键-“属性”-“高级系统设置”-“高级”-“环境变量”:

  备注:使用npm install -g \'xxx\' 之后仍然报Cannot find module \'xxx\' 错误,可以通过设置环境变量NODE_PATH来解决。

  在系统目录中找到C:\\Users\\Administrator\\.npmrc文件 修改如下即可:

          prefix =D:\\Develop\\nodejs\\node_global 
          cache =D:\\Develop\\nodejs\\node_cache
  配置完后,安装几个module测试下,我们就安装最常用的express模块,打开cmd窗口,输入如下命令进行模块的全局安装:npm install express -g # -g是全局安装的意思

3、自签名的https证书 

  openssl genrsa -out 1557605_www.learningrtc.cn.key 2048//这是秘钥(生成秘钥文件)
  openssl req -new -sha256 -key 1557605_www.learningrtc.cn.key -out csr.pem//签名请求文件(申请者需要将自己的信息及其公钥放入证书请求中。但在实际操作过程中,所需要提供的是私钥而非公钥,因为它会自动从私钥中提取公钥)
  openssl x509 -req -in csr.pem -signkey 1557605_www.learningrtc.cn.key -out 1557605_www.learningrtc.cn.pem//这是证书

4、信令服务器主要代码

    server.js文件

\'use strict\'

var log4js = require(\'log4js\');
var http = require(\'http\');
var https = require(\'https\');
var fs = require(\'fs\');
var socketIo = require(\'socket.io\');

var express = require(\'express\');
var serveIndex = require(\'serve-index\');

var USERCOUNT = 3;

log4js.configure({
    appenders: {
        file: {
            type: \'file\',
            filename: \'app.log\',
            layout: {
                type: \'pattern\',
                pattern: \'%r %p - %m\',
            }
        }
    },
    categories: {
       default: {
          appenders: [\'file\'],
          level: \'debug\'
       }
    }
});

var logger = log4js.getLogger();

var app = express();
app.use(serveIndex(\'./public\'));       //node server.js启动后,项目的根目录在public文件夹下(public文件夹和server.js文件在同一个目录下,public文件夹下有index.html文件、css文件和js文件夹等)
app.use(express.static(\'./public\'));   



//http server
var http_server = http.createServer(app);
http_server.listen(80, \'0.0.0.0\');

var options = {
    key : fs.readFileSync(\'./cert/1557605_www.learningrtc.cn.key\'), //https秘钥,放在cert文件夹下
    cert: fs.readFileSync(\'./cert/1557605_www.learningrtc.cn.pem\')  //https证书,放在cert文件夹下
}

//https server
var https_server = https.createServer(options, app);
var io = socketIo.listen(https_server);

io.sockets.on(\'connection\', (socket)=> {

    socket.on(\'message\', (room, data)=>{
        logger.debug(\'message, room: \' + room + ", data, type:" + data.type);
        socket.to(room).emit(\'message\',room, data);
    });

    /*
    socket.on(\'message\', (room)=>{
        logger.debug(\'message, room: \' + room );
        socket.to(room).emit(\'message\',room);
    });
    */

    socket.on(\'join\', (room)=>{
        socket.join(room);
        var myRoom = io.sockets.adapter.rooms[room]; 
        var users = (myRoom)? Object.keys(myRoom.sockets).length : 0;
        logger.debug(\'the user number of room (\' + room + \') is: \' + users);

        if(users < USERCOUNT){
            socket.emit(\'joined\', room, socket.id); //发给除自己之外的房间内的所有人
            if(users > 1){
                socket.to(room).emit(\'otherjoin\', room, socket.id);
            }
        
        }else{
            socket.leave(room);    
            socket.emit(\'full\', room, socket.id);
        }
        //socket.emit(\'joined\', room, socket.id); //发给自己
        //socket.broadcast.emit(\'joined\', room, socket.id); //发给除自己之外的这个节点上的所有人
        //io.in(room).emit(\'joined\', room, socket.id); //发给房间内的所有人
    });

    socket.on(\'leave\', (room)=>{

        socket.leave(room);

        var myRoom = io.sockets.adapter.rooms[room]; 
        var users = (myRoom)? Object.keys(myRoom.sockets).length : 0;
        logger.debug(\'the user number of room is: \' + users);

        //socket.emit(\'leaved\', room, socket.id);
        //socket.broadcast.emit(\'leaved\', room, socket.id);
        socket.to(room).emit(\'bye\', room, socket.id);
        socket.emit(\'leaved\', room, socket.id);
        //io.in(room).emit(\'leaved\', room, socket.id);
    });

});

https_server.listen(8443, \'0.0.0.0\');

index.html文件:

<html>
    <head>
        <title>Chat Room</title>
        <link rel="stylesheet" href="./css/main.css"></link>
    </head>
    <body>
        <table align="center">
            <tr>
                <td>
                    <label>UserName: </label>
                    <input type=text id="username"></input>
                </td>
            </tr>
            <tr>
                <td>
                    <label>room: </label>
                    <input type=text id="room"></input>
                    <button id="connect">Conect</button>
                    <button id="leave" disabled>Leave</button>
                </td>
            </tr>
            <tr>
                <td>
                    <label>Content: </label><br>
                    <textarea disabled style="line-height: 1.5;" id="output" rows="10" cols="100"></textarea>
                </td>
            </tr>
            <tr>
                <td>
                    <label>Input: </label><br>
                    <textarea disabled id="input" rows="3" cols="100"></textarea>
                </td>
            </tr>
            <tr>
                <td>
                    <button id="send">Send</button>
                </td>
            </tr>
        </table>

        <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
        <script src="./js/client.js"></script> 
    </body>

</html>

client.js文件:

\'use strict\'

var userName = document.querySelector(\'input#username\');
var inputRoom = document.querySelector(\'input#room\');
var btnConnect = document.querySelector(\'button#connect\');
var btnLeave = document.querySelector(\'button#leave\');
var outputArea = document.querySelector(\'textarea#output\');
var inputArea = document.querySelector(\'textarea#input\');
var btnSend = document.querySelector(\'button#send\');

var socket;
var room;

btnConnect.onclick = ()=>{

    //connect
    socket = io.connect(); 
    
    //recieve message
    socket.on(\'joined\', (room, id) => {
        btnConnect.disabled = true;
        btnLeave.disabled = false;
        inputArea.disabled = false;
        btnSend.disabled = false;
        alert("room:"+room + ",id:"+id);
    });    
    
    socket.on(\'leaved\', (room, id) => {
        btnConnect.disabled = false;
        btnLeave.disabled = true;
        inputArea.disabled = true;
        btnSend.disabled = true;

        socket.disconnect();
    });    

    socket.on(\'message\', (room, data) => {
        outputArea.scrollTop = outputArea.scrollHeight;//窗口总是显示最后的内容
        outputArea.value = outputArea.value + data + \'\\r\';
    });    

    socket.on(\'disconnect\', (socket)=>{
        btnConnect.disabled = false;
        btnLeave.disabled = true;
        inputArea.disabled = true;
        btnSend.disabled = true;
    });

    //send message
    room = inputRoom.value;
    socket.emit(\'join\', room);
}

btnSend.onclick = ()=>{
    var data = inputArea.value;
    data = userName.value + \':\' + data;
    socket.emit(\'message\', room, data);
    inputArea.value = \'\';
}

btnLeave.onclick = ()=>{
    room = inputRoom.value;
    socket.emit(\'leave\', room);
}

inputArea.onkeypress = (event)=> {
    //event = event || window.event;
    if (event.keyCode == 13) { //回车发送消息
    var data = inputArea.value;
    data = userName.value + \':\' + data;
    socket.emit(\'message\', room, data);
    inputArea.value = \'\';
    event.preventDefault();//阻止默认行为
    }
}

5、启动服务

    cmd窗口,进入项目位置,输入:node server.js   启动服务。

    Chrome浏览器和360极速浏览器,页面分别输入https://localhost:8443/index.html,加入同一个房间,可以发送聊天信息,房间里的用户可以识别到新加入的用户(收到join等消息)。


参考地址:
https://blog.csdn.net/u012853084/article/details/79089946

https://blog.csdn.net/paulowina/article/details/78591432

https://blog.csdn.net/abccheng/article/details/82622899

https://www.iteye.com/blog/freeman983-1350861

以上是关于Nodejs搭建音视频通信 信令服务器的主要内容,如果未能解决你的问题,请参考以下文章

音视频技术开发周刊 93期

应用关闭时实现 Agora 信令进行通信

Socket.io vs RTCDataChannel,作为信令服务器?

webrtc博客收藏

MQTT作为WebRTC信令

一文看懂音视频流媒体协议及信令技术