美文网首页
Mac上webrtc实现简易聊天室

Mac上webrtc实现简易聊天室

作者: 一叶知秋0830 | 来源:发表于2019-08-08 15:42 被阅读0次

    一、搭建信令服务器

    首先创建一个文件夹chatRoom用来存放项目文件,chatRoom文件中创建pem文件夹存放证书,创建public文件夹用于存放要发布的文件,创建server.js文件(信令服务器文件),server.js文件中代码如下。我这里是搭建的本地服务器,会涉及到证书的生成,可以参考:生成自签名证书。搭建好后将服务启动,这时会看到chatRoom文件夹中多了一个app.log文件,这个是日志文件,服务器运行中的日志都存在这个文件中。

    // server.js文件代码
    
    // 引入所需的各个模块
    var http = require('http');
    var https = require('https');
    var fs = require('fs'); // 用于读取证书
    var express = require('express');
    var serve_index = require('serve-index');
    // 引入socket.io,socket.io是一个WebSocket库,用于实现在不同浏览器和移动设备上进行实时通信。
    // 安装socket.io模块的命令:sudo npm install socket.io -g
    var socketIo = require('socket.io'); 
    // 引入log4js,用于日志输出
    // 安装log4js模块的命令:sudo npm install log4js -g
    var log4js = require('log4js');
    // log4js的配置(日志内容存储在app.log的文件中)
    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();
    
    // 定义一个express对象,用于web服务
    var app = express();
    // 发布静态目录,静态目录是当前路径下的public文件夹
    app.use(serve_index('./public', {'icons': true}));
    app.use(express.static('./public'));
    
    // http服务
    var http_server = http.createServer(app);
    http_server.listen(8082,'192.168.20.242');
    
    // https服务
    // 读取证书
    var options = {
       key : fs.readFileSync('./pem/private_key.pem'),
       cert : fs.readFileSync('./pem/cacert.pem')
    };
    var https_server = https.createServer(options,app);
    
    /*
    将socket.io与https_server绑定起来
    当启动服务时socket.io和https_server这2个服务都是绑定在8083端口上
    绑定的服务io(站点)下面可以有很多房间
    */
    var io = socketIo.listen(https_server);
    /*
    io下面所有socket(一个socket就是一个链接,也就是一个客户端)都监听connection事件。
    当一个客户端链接进来后底层就会发送一个connection消息过来
    后面的匿名函数就是收到connection消息时要执行的函数,参数socket就是接收到消息的socket
    */
    io.sockets.on('connection',(socket)=>{
        // socket监听加入房间的消息(join是我们自己定义的加入房间的消息),room是要加入的房间
        socket.on('join',(room)=>{
            // 加入房间(如果是第一个用户还没有房间的话就会自动创建一个房间)
            socket.join(room);
            // 根据房间标示获取房间
            var myRoom = io.sockets.adapter.rooms[room];
            if (myRoom) {
                // 获取房间人数(myRoom.sockets是房间所有用户)
                var userNum = Object.keys(myRoom.sockets).length;
                logger.info("当前房间人数为:"+userNum);
            }
            // 加入房间成功后可以给客户端回一个消息,joined是加入成功的消息,room和socket.id是回的参数
            socket.emit('joined',room,socket.id); // 给他本人回
            // socket.to(room).emit('joined',room,socket.id); // 给房间里除了自己外的所有人回
            // io.in(room).emit('joined',room,socket.id); // 给房间里的所有人回(注意这里是io调用的)
            // socket.broadcast.emit('joined',room,socket.id); // 给除了自己外所有站点的人回
        });
    
        // socket监听离开房间的消息
        socket.on('leave',(room)=>{
            var myRoom = io.sockets.adapter.rooms[room];
            if (myRoom) {
                // 获取房间人数,离开房间后房间人数会-1
                var userNum = Object.keys(myRoom.sockets).length;
                logger.info("当前房间人数为:"+(userNum-1));
            }
            socket.leave(room);
            socket.emit('leaved',room,socket.id); // 给他本人回
            // socket.to(room).emit('leaved',room,socket.id); // 给房间里除了自己外的所有人回
            // io.in(room).emit('leaved',room,socket.id); // 给房间里的所有人回(注意这里是io调用的)
            // socket.broadcast.emit('leaved',room,socket.id); // 给除了自己外所有站点的人回
        });
    
        // socket监听发送消息
        socket.on('message',(room,data)=>{
            // 收到消息后将消息发给房间所有人
            io.in(room).emit('message',room,socket.id,data);
        });
    });
    
    https_server.listen(8083,'192.168.20.242');
    

    二、创建前端页面

    前端页面效果如下图所示。开始时"加入房间"按钮可以点击,"离开房间"、"发送消息"和两个消息框都是禁用的,加入房间成功后"加入房间"按钮禁用,其他按钮和消息框变成可用状态。


    前端页面效果图

    在public目录下创建一个index.html文件,代码内容如下

    // 前端页面代码
    
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>webrtc实现简易聊天室</title>
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <!-- socket.io的js文件 -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
    </head>
    <body>
        
        <div>
            <label>用户名:</label>
            <input type="text" id="username"></input>
        </div>
    
        <div>
            <label>房间号:</label>
            <input type="text" id="room"></input>
            <button id="joinBtn">加入房间</button>
            <button disabled id="leaveBtn">离开房间</button>
        </div>
    
        <div>
            <label>消息:</label>
            <br>
            <textarea disabled id="output" style="line-height: 1.5" rows="10" cols="100"></textarea>
        </div>
    
        <div>
            <label>输入框:</label>
            <br>
            <textarea disabled id="input" style="line-height: 1.5" rows="3" cols="100"></textarea>
            <br>
            <button disabled id="sendBtn">发送消息</button>
        </div>
    
        <script type="text/javascript" src="js/client.js"></script>
    </body>
    </html> 
    

    三、前端JS文件

    在public目录下新建一个js目录,在js目录下创建一个client.js文件,代码内容如下:

    // 前端js文件代码
    
    
    'use strict'
    
    var outputBox = $("#output")[0];
    var inputBox = $("#input")[0];
    var socket;
    var room;
    
    // 点击加入房间按钮
    $("#joinBtn").click(function(){
        room = $("#room").val();
        console.log('111');
        // io调用connect方法,底层会给信令服务器发送connection消息
        socket = io.connect();
    console.log('222');
        // 监听消息
        //监听加入房间成功的消息(加入房间成功后信令服务器会回一个joined消息)
        socket.on('joined',(room,id)=>{
            // 加入房间成功后对改变前端页面控制的状态
            $("#joinBtn").attr('disabled',true);
            $("#leaveBtn").attr('disabled',false);
            $("#output").attr('disabled',false);
            $("#sendBtn").attr('disabled',false);
            $("#input").attr('disabled',false);
        })
        // 监听离开房间成功的消息(离开房间成功后信令服务器会回一个leaved消息)
        socket.on('leaved',(room,id)=>{
            // 离开房间成功后对改变前端页面控制的状态
            $("#joinBtn").attr('disabled',false);
            $("#leaveBtn").attr('disabled',true);
            $("#output").attr('disabled',true);
            $("#sendBtn").attr('disabled',true);
            $("#input").attr('disabled',true);
        });
        // 监听接收消息(有新消息时信令服务器会发一个message消息)
        socket.on('message',(room,id,data)=>{
            outputBox.scrollTop = outputBox.scrollHeight;//窗口总是显示最后的内容
            outputBox.value = outputBox.value + data + '\r';// 将新消息拼接在原消息后面
        });
    
        // 发送加入房间的消息
        socket.emit('join',room);
    });
    
    // 点击离开房间按钮
    $("#leaveBtn").click(function(){
        // 发送离开房间的消息
        socket.emit('leave',room);
    });
    
    // 点击发送消息按钮
    $("#sendBtn").click(function(){
        var data = $("#username").val()+":"+$("#input").val();
        // 发送消息,信令服务器收到消息后会将消息发给房间的每一个人
        socket.emit('message',room,data);
        $("#input").val('');
    });
    

    四、测试

    多打开几个浏览器页面,在地址栏输入https://192.168.20.242:8083/index.html,也可以在手机端浏览器输入这个地址(由于是本地服务器,所以需要手机和电脑连的是同一个局域网才行),每个页面都输入不同的用户名和同一个房间名,然后点击'加入房间'按钮,加入成功后在输入框输入消息并发送,可以看到所有页面的消息框都可以收到消息。

    聊天室测试效果

    相关文章

      网友评论

          本文标题:Mac上webrtc实现简易聊天室

          本文链接:https://www.haomeiwen.com/subject/ftyulctx.html