Mac上webrtc实现简易聊天室
2019-08-08 本文已影响0人
一叶知秋0830
一、搭建信令服务器
首先创建一个文件夹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
,也可以在手机端浏览器输入这个地址(由于是本地服务器,所以需要手机和电脑连的是同一个局域网才行),每个页面都输入不同的用户名和同一个房间名,然后点击'加入房间'按钮,加入成功后在输入框输入消息并发送,可以看到所有页面的消息框都可以收到消息。