Node.js + Socket实现移动端聊天程序

在这个学期的计算机网络原理的实验任务二中,要求学生可以选做基于Socket编程的聊天程序。考虑到之前学习过Node.js,结合去年暑假开发跨端APP的经验,决定边学边做,实现一个简单的实时聊天程序。大概用时两天。当然,整体时间还是很紧张的。

使用前后端分离的方式进行开发。

前端使用uni-app跨端框架。后端使用Express框架。

1. 录屏展示

Socket实时聊天室-演示视频

2. 前端

  • Vue.js + uni-app + weapp.socket.io
  • scss实现样式

3. 后端

  • Express(Node.js Web应用程序框架) + Socket.IO
  • 建立一个专门用来即时通讯的端口8081

4. 流程图

  • 客户端-服务端-多个客户端
  • 客户端、服务端:都是接收和发送两个处理
  • 服务端:广播

5. 实际效果

(1)启动后端

(2)启动前端

可以在HBuilderX里,选择直接运行到浏览器。当然,同样支持真机调试和模拟器调试。

(3)功能演示

  • 默认页
  • 支持选择头像
  • 输入用户名后点击”加入“。
  • 我们可以以不同的身份加入。每个用户加入群聊后都会显示欢迎语。同样地,可以在群里中发送消息。
  • 分别以李四和王五的身份加入聊天室。加入后三人的界面如下。
张三的界面
李四的界面
王五的界面
  • 在三人都加入群聊后,李四发布一条消息。
  • 此时张三和王五也都可以在各自的界面里收到李四的消息。
  • 如果关闭页面,或者返回上一级页面,即认为该用户退出。如果刷新页面,认为该用户是退出后重新进入聊天室。如图,我们关闭王五的界面。刷新重进李四的界面。
  • 刷新重进后不保存之前的聊天记录。因为考虑到时间有限,没有设计数据库。
  • 下面演示私聊功能。
  • 在学生发送消息后,老师的界面上该学生的头像上会显示红点。打开消息后红点消失。
  • 如图,接收消息是成功的。同样的,回复消息也是成功的。学生和老师都可以在各自的界面看到这几条消息。对方发过来的消息显示在左侧,自己发出去的消息显示在右侧。支持查看发送消息的具体时间。
  • 其他细节:
    • 群聊时,对于自己发送的消息,只显示消息发送时间。对于接受到的对方发送的消息,显示对方用户名和消息发送时间。
    • 头部导航栏不显示自己的头像,只显示其他可私聊群成员的头像。

6. 相关代码和说明

  • 注意使用合适的依赖版本
 "dependencies": {
    "express": "^4.17.1",
    "socket.io": "^2.3.0"
  }
  • 大概的流程:
    • 客户端使用this.socket.emit(‘msg’,data);发送信息
    • 服务端使用socket.on接收消息
    • 服务端使用socket.broadcast.emit广播消息
    • 客户端接收广播后的消息并渲染
    • 具体细节还需要看Socket.IO官方文档 https://socket.io
  • 客户端需要用到简单的JavaScript数组方法插入数据。
  • 服务端需要建立Socket.IO对象。

7. 小结

  • 前端(客户端)代码量相对最大,很多是样式方面的代码。此外,函数方面举例:
    • 获取当前日期
    • 发送消息
    • 加入群聊
    • 欢迎消息
    • 获取个人信息
    • 退出群消息提醒
    • 获取即时信息渲染
    • 获取私聊信息
    • 进入私聊
    • 私聊界面动画
    • 退出
  • 后端(服务端)代码其实非常简洁。也要感谢网上的相关参考教程。
const express = require('express')
const app = express()
const port = 3000

let server = app.listen(8081)
let io = require('socket.io').listen(server);
//引入socket.js
require('./model/socket.js')(io);


app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => console.log(`项目已经在端口${port}启动!`))
module.exports = function(io){
    let socketList = {};
    let users = [];

    io.sockets.on('connection',function(socket){
        console.log('连接到http://10.4.9.73:8081成功!');
        socket.on('join',(name,img) => {
            socket.name = name;
            socketList[name] = socket.id;
            let user = {name:name,img:img,id:socket.id,tip:false};
            users.push(user);

            socket.broadcast.emit('welcome',name,users);
            socket.emit('myself',name,users,socket.id);
        });
        // 接收信息
        socket.on('message',data => {
            // 广播
            socket.broadcast.emit('sendMsg',data);
        })
        // 私聊信息
        socket.on('msg',data => {
            //console.log(data.tid);
            // 广播
            socket.to(data.tid).emit('sMsg',data);
        })

        // 用户离开
        socket.on('disconnecting',function(){
            if(socketList.hasOwnProperty(socket.name)){
                // 删除
                delete socketList[socket.name];
                for(let i=0;i<users.length;i++){
                    if(users[i].name == socket.name){
                        users.splice(i,1);
                    }
                }
                // 广播用户退出
                socket.broadcast.emit('quit',socket.name,users);
            }
        })
    })
}

发表评论