200 行代码实现 web 在线聊天室 (websocket)

8,162 阅读4分钟

项目介绍

基于websocket的一个简单的聊天室

技术栈 express+socket.io+animate.css+angular
关于websocket不了解的点我,而socket.io是对websocket进行封装,提供通用接口。
Github项目地址

安装与使用

git clone https://github.com/ShanaMaid/websocket-express-webchat.git  #下载项目
npm install  #安装依赖
node app.js  #启动服务
访问  http://localhost/  #进入聊天室

功能

  • 进入房间通知
  • 离开房间通知
  • 消息接收与发送
  • 在线列表
  • 服务器端信息备份

动态GIF

聊天室

聊天室

在线聊天室Demo

手机与电脑均可访问,点我进入在线版

实现

思路

利用on绑定事件,emit触发绑定事件,服务器端与客户端进行交互

socket.on(eventName,callBack)  #绑定事件,eventName可以自定义
socket.emit(eventName,data) #触发事件,发送data

更多关于socket.io的详细信息请移步官方文档,点我

服务端

首先添加我们需要使用的模块

var express = require('express');
var socket = require('socket.io');
var fs = require('fs');

然后从配置文件config.json读取一些我们需要的关于聊天室的一些配置信息,关于配置文件

var history_num = config.history_num ; //服务器缓存的历史消息条数
var port = config.sever_port;   //端口号
var backup = config.backup; //是否开启备份
var backup_filename = config.backup_filename; //备份文件名字

定义person与history两个数组,用于存储在线人员的名称与服务端缓存的消息条数(即用户第一次进入聊天室推送的历史消息条数)

var person = [];//记录在线情况
var history = [];//需要缓存的消息

监听port端口号,创建一个socket对象io

var app = express();
var server = app.listen(port);
var io = new socket(server);

编写connection事件,响应客户端的连接请求,返回客户端socket,编写客户端要emit的事件
…………………………表示代码省略部分,完整代码点击Github项目地址

io.on('connection',  (socket) => {
    …………………………  
    socket.emit('history',history); #发送服务器记录的历史消息
    io.sockets.emit('updatePerson', person); #进行广播,触发所有客户端的updatePerson事件,更新在线列表人员
    ………………………… 
    socket.on('sendMsg', (data) => { #发送消息事件
        …………………………
        io.sockets.emit('news',obj); #进行广播,触发所有客户端的news事件,更新信息。
    });
    socket.on('setUserName',(data) => { #设定用户名事件
        …………………………
        io.sockets.emit('updatePerson',person); #进行广播,触发所有客户端的updatePerson事件,更新在线列表人员
        io.sockets.emit('news',{content:user+'进入房间',time:Now(),name:'系统消息'}); #进行广播,触发所有客户端的news事件,通知进入房间
        …………………………
    });
    socket.on('disconnect',  (socket) => { #掉线事件
        if(user!='') {
            io.sockets.emit('news', {content: user + '离开房间', time: Now(), name: '系统消息'}); #进行广播,离开房间
            person.splice(id,1);
        }
        io.sockets.emit('updatePerson', person);
    });
});

客户端

变量初始化

$scope.data = [];    #接收-消息队列
$scope.name = '';       #用户名
$scope.content = '';    #发送信息内容
$scope.personnum = 0;   #在线人数
$scope.personlist = []; #在线人员列表
$scope.flag = false;    #是否取名

创建客户端socket

const socket_url = 'http://localhost';
var socket = io(socket_url);

完成服务器端的emit的事件

socket.on('news', (data) => {
   ……………………
});
socket.on('history', (data) => {
    ……………………
});
socket.on('updatePerson', (data) => {
    ……………………
});

config.json配置文件

{
  "history_num":20,  #服务器缓存的历史信息条数
  "sever_port":80,  #服务器监听端口号
  "backup":true,    #是否开启服务端信息备份
  "backup_filename":"./backup/example.json"  #备份文件名字
}

聊天信息备份

聊天信息以json格式存储在example.json文件中!

function backupMsg(filename,obj) {
    var backup_file = fs.readFileSync(backup_filename);
    var msg= backup_file!='' ? JSON.parse(backup_file) : [];
    msg.push(obj);
    var str = '[\n'
    msg.forEach((value,index) =>{
        if (index!==0){
            str+=',\n';
        }
        str += '  {\n    "name":"'+value.name+'",\n    "time":"'+value.time+'",\n    "content":"'+value.content+'"\n  }'
    } );
    str += '\n]';
    fs.writeFile(filename, str, (err) => {
        if(err)
            console.log("fail write :" + arr +  "   "+Date() + "\n error:"+err);
    });
}

备份信息示例

[
  {
    "name":"测试人员1",
    "time":"2017-2-13  23:32:17",
    "content":"一条简单的测试信息"
  },
  {
    "name":"测试人2",
    "time":"2017-2-13  23:33:42",
    "content":"那你很棒哦"
  },
  {
    "name":"测试人3",
    "time":"2017-2-13  23:33:54",
    "content":"肯定很棒哦"
  }
]

总结

websocket实现了浏览器与服务器全双工通信。
举个栗子,原来是这样的
轮询机制:

客户端:服务器,你有没有消息要给我啊?
服务器:有。
客户端:服务器,你有没有消息要给我啊?
服务器:没有。
——————————无限重复————————————
客户端:服务器,你有没有消息要给我啊?
服务器:没有。
客户端:服务器,你有没有消息要给我啊?
服务器:你烦不烦啊~

而现在的websocket:

客户端:服务器,你有我的消息了记得call我。
服务器:OK!
——————————当有消息的时候————————
服务器:有你的消息了,客户端。
客户端:收到。

Github项目地址,欢迎各位交流学习!

坚持原创技术分享,您的支持将鼓励我继续创作! 赏 ShanaMaid Alipay

支付宝打赏