Websocket 初体验+本地搭建聊天室

写在前面

  1. 项目使用node在本地搭建,使用的是Koa框架 中间件涉及 koa-static/koa-websocket。
  2. 因为是本地服务没有写数据库操作,有兴趣的朋友可以把聊天记录做本地保存。
  3. 前端使用的Vue+elementUI 只写了基础的功能 。
  4. 涉及知识:nodeJS+后端服务+websocket协议

项目已上传到Github

点击这里跳转到 Git Hub Websocket

1.搭建koa静态服务

首先引入koa、koa-router、koa-static等服务需要中间件,引入配置文件use中间件然后挂载静态服务处理,以及路由处理,在这里我是分模块引入了,具体看代码。
Websocket 初体验+本地搭建聊天室_第1张图片

2.搭建Websocket服务

引入相应模块,并监听80端口。
这里可能会有一些疑问,这里的app.ws其实相当于总管,只要有一个用户进来我就在实例下创建一个服务线程,总管就多一个员工。每个服务线程会生成一个上下文,每个上下文主体其实是这个websocket,直接用ctx会报错,在第一次接收到信息时也就是第一次登录时会记录登录ID给这个对象,这样就可以不同用户享受同样的服务,只需要判断你想要的服务是什么。

app.ws.use((ctx, next) => {
    /* 每打开一个连接就往 CTXS 添加一个上下文 */
 ctxs.push(ctx);/*来一个我就管理一个 记录名单*/
 ctx.websocket.on("message", (message) => {
        var data = JSON.parse(message);//处理数据
        // data.type = "msg";
        if(data.user.type == "login"){//初始化员工ID
 ctx.websocket.id = data.user.uid;
 console.log("用户"+ data.user.uid +"加入聊天室");
        }else if(data.type=="chat"){//聊天模式 分配对应数据
            var need = {
 send_time:data.send_time,
 msg:data.user.send_msg,
 type:'msg',
 uname:data.user.uname,
 uid:data.user.uid,
 uimg: data.user.uimg
            };
 ctxs.forEach((s)=>{
                /* 接收者  */
                if(s.websocket.id==data.receiver.uid&&s.websocket.readyState==1){
 s.websocket.send(JSON.stringify(need));
                }
                /* 发送者提示 */
                if(s.websocket.id==data.user.uid&&s.websocket.readyState==1){
 s.websocket.send(JSON.stringify({msg:"发送成功!",status:1,error:0,type:'tip'}));
                }
                if(s.websocket.id==data.user.uid&&s.websocket.readyState==3){
 s.websocket.send(JSON.stringify({msg:"发送失败!",status:0,error:1,type:'tip'}));
                }
            })
        }
    });
 ctx.websocket.on("close", (message) => {
        /* 连接关闭时, 清理 上下文数组, 防止报错 */
        let index = ctxs.indexOf(ctx);
 console.log(ctxs[index].websocket.id+"关闭了链接")
 ctxs.splice(index, 1);
    });
});

有小伙伴会问了,这里为什么要循环呢?
这里循环是要找到员工也就是对应ID的websocket服务,然后员工对应前台登录的用户,因为这里是一对一聊天,当然服务也是一对一,这里举个栗子:

  1. 小张到酒吧点了一杯小鸟伏特加,他告诉服务员他的要求‘就要这么高’‘要哈拉少的’‘点名要1号调酒师’(这里服务员得到的信息:用户ID、小鸟伏特加 用量 刺激程度 要找的调酒师等)
  2. 服务员回去告诉吧台这些信息,吧台在一张总表上按顺序记录了所有用户的信息以及需求。(我是总管,他们的信息我全都知道)
  3. 1号调酒技师通过吧台的所有信息找到自己需要做的。
  4. 到这里就完成了小张和调酒师的对话。

**逻辑:
我登录服务器——》服务器记录我的登录ID——》我找人聊天——》告诉服务器我找的人的ID、还有我要说的信息——》服务器帮我找到我要找的人———》帮我把信息发送给他。

1.前端建立Websocket服务

 var CreateWebSocket = (function () {
            return function (urlValue) {
                if (window.WebSocket) return new WebSocket(urlValue);
                if (window.MozWebSocket) return new MozWebSocket(urlValue);
                return false;
            }
        })();
        /* 实例化 WebSocket 连接对象, 地址为 ws 协议 */
        var webSocket = CreateWebSocket("ws://localhost");

2.前端发送消息

前端发送消息主要步骤为:建立服务(此时为登录服务器,服务器会记录用户ID)——》获取输入信息、收信人ID、发送时间等——》保存本地聊天记录并更新视图——》通过Websocket发送信息——》服务器接受信息并处理。

ws_send: function () {
                    /* 发送消息 */
                    let odate = new Date();
                    send_time = odate.toLocaleString();
                    let alldata = JSON.stringify({
                        user: this.chat_user,//发送者 当前用户
                        receiver: this.chat_friend,//接收人 当前聊天的对象
                        send_time,//发送时间
                        type: 'chat'//类型 
                    });
                    if (!this.chat_record.hasOwnProperty(this.chat_friend.uid)) this.chat_record[this
                        .chat_friend.uid] = [];
                    if (this.chat_friend.uid != this.chat_user.uid) {
                        // this.chat_record[this.chat_friend.uid].push()
                        this.$set(this.chat_record[this.chat_friend.uid], this.chat_record[this.chat_friend
                            .uid].length, {
                            send_time,
                            msg: this.chat_user.send_msg,
                            ...this.chat_user
                        });
                    }
                    webSocket.send(alldata);
                    var ele = document.getElementById('recordList');
                    ele.scrollTop = ele.scrollHeight;
                    this.chat_user.send_msg = '';
                },

3.前端接受消息

前端接受消息主要步骤为:监听服务——》获取所有信息(服务器已处理信息)——》加入聊天记录——》更新视图。

rceiverMsg: function (data) {
                    let {
                        send_time,
                        msg,
                        uname,
                        uid,
                        uimg
                    } = {
                        ...data
                    };
                    let id = uid + '';
                    if (!this.chat_record.hasOwnProperty(id)) this.chat_record[id] = [];
                    this.$set(this.chat_record[id], this.chat_record[id].length, {
                        send_time,
                        msg,
                        uname,
                        uid,
                        uimg
                    });
                    this.$forceUpdate();
                },

具体的代码实现思路大概就是这些,websocket就相当于一个中间商帮你找到对应的用户,作为一个中间者传递消息。

写在最后

我是工作一年多的前端工程师,喜欢关注一些前端全栈有趣的东西,目标是从前端走向全栈,后续工作之余还会更新一个群聊的Websocket,有兴趣的小伙伴可以关注我哟!
如果小伙伴看了我的文章由什么启发或者有什么疑惑的话都可以在下面评论或者私信我!

你可能感兴趣的:(Websocket 初体验+本地搭建聊天室)