nodejs socket实现简单的文字聊天记录2

目录如下

 从上到下分别是node聊天服务,客户端代码,websocket封装类

代码文件如下

1.chatServer.js

let ws = require("nodejs-websocket");
process.stdin.setEncoding("utf8");
console.log("开始建立连接...");
let userObj = {};
let server = ws
  .createServer(function (conn) {
    conn.on("text", function (str) {
      let newStr = eval("(" + str + ")");

      const { memberId, targetId, content } = newStr;
      console.log("收到的信息为:" + content);
      console.log("用户id:" + memberId);
      userObj[memberId] = {
        coon: conn,
        isOnline: true,
      };

      if (content !== "已经建立连接") {
        //如果接收方在线
        if (userObj[targetId]) {
          userObj[targetId].coon.sendText(memberId + ":" + content);
        }
        conn.sendText(memberId + ":" + content);
      }

      //像前端页面发送推送
      process.stdout.write("请输入发送的值:");
      process.stdin.on("data", function (chunk) {
        conn.sendText(chunk);
      });
    });

    conn.on("close", function (code, reason) {
      console.log("关闭连接");
    });
    conn.on("error", function (code, reason) {
      console.log("异常关闭");
    });
  })
  .listen(8801);
console.log("WebSocket建立完毕");

2.websocketClass.js

export default class Websocket {
  static getInstance() {
    if (!this.instance) {
      this.instance = new websocket();
    }
    return this.instance;
  }
  constructor(props) {
    this.instance = null;
    this.heartConfig = {
      timeout: 100000, //9分钟发一次心跳
    };
    this.ws = null;
    this.lockReconnect = false;
    this.wsUrl = null;
    this.socketEventHandle = null;
  }
  //创建一个websocket
  createWebSocket({ url, socketEventHandle }) {
    let that = this;
    that.wsUrl = url;
    that.socketEventHandle = socketEventHandle;
    try {
      if ("WebSocket" in window) {
        that.ws = new WebSocket(url);
      } else if ("MozWebSocket" in window) {
        that.ws = new MozWebSocket(url);
      } else {
        alert(
          "您的浏览器不支持websocket协议,建议使用新版谷歌、火狐等浏览器,请勿使用IE10以下浏览器,360浏览器请使用极速模式,不要使用兼容模式!"
        );
      }

      that.initEventHandle();
    } catch (e) {
      that.reconnect(url);
      console.log(e);
    }
  }

  //ws事件处理
  initEventHandle() {
    let that = this;
    that.ws.onclose = function () {
      that.reconnect(that.wsUrl);
      console.log("ws连接关闭!" + new Date().toUTCString());
      that.socketEventHandle({ type: "onclose" });
    };
    that.ws.onerror = function () {
      that.reconnect(that.wsUrl);
      console.log("ws连接错误!");
      that.socketEventHandle({ type: "onerror" });
    };
    that.ws.onopen = function () {
      that.heartCheck().reset().start(); //心跳检测重置
      that.socketEventHandle({ type: "onopen" });
    };
    that.ws.onmessage = function (event) {
      //如果获取到消息,心跳检测重置
      that.heartCheck().reset().start(); //拿到任何消息都说明当前连接是正常的
      that.socketEventHandle({ type: "sendMessage", message: event.data });
    };
  }

  //重连
  reconnect(url) {
    let that = this;
    if (that.lockReconnect) return;
    that.lockReconnect = true;
    setTimeout(function () {
      //没连接上会一直重连,设置延迟避免请求过多
      that.createWebSocket(url);
      that.lockReconnect = false;
    }, 2000);
  }

  //关闭连接
  closeWebSocket() {
    this.ws.close();
  }

  //发送消息
  sendMessage(sendStr) {
    this.ws.send(sendStr);
  }

  //心跳检查
  heartCheck() {
    let that = this;
    //心跳检测
    return {
      timeout: 5 * 60 * 1000, //5分钟发一次心跳
      timeoutObj: null,
      serverTimeoutObj: null,
      // ...that.heartConfig,
      reset: function () {
        var self = this;
        clearTimeout(self.timeoutObj);
        clearTimeout(self.serverTimeoutObj);
        return self;
      },
      start: function () {
        var self = this;
        self.timeoutObj = setTimeout(function () {
          //这里发送一个心跳,后端收到后,返回一个心跳消息,
          //onmessage拿到返回的心跳就说明连接正常
          that.ws.send("ping");
          console.log("ping!");
          self.serverTimeoutObj = setTimeout(function () {
            //如果超过一定时间还没重置,说明后端主动断开了
            that.ws.close(); //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
          }, self.timeout);
        }, self.timeout);
      },
    };
  }
}



3.user.html

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8">
    <title>websocket(用户1)</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
        integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>

<body>
    <div class="col-sm-6">
        <ul id="chat-list"></ul>

        <div class="form-group">
            <p></p>
            <textarea id="chatBox" class="col-sm-2 form-control" rows="3" style="margin-bottom:10px"></textarea>
            <button type="button" class="btn btn-primary" id="Bridge"
                style="float: left;margin-right: 10px">建立连接</button>
            <button type="button" id='btnSend' class="btn btn-success">发送信息</button>
        </div>
    </div>
</body>

<script type="module">

    import Websocket from './websocketClass.js';
    function getParam(url, name) {
        try {
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
            var r = url.split('?')[1].match(reg);
            if (r != null) {
                return r[2];
            }
            return "";//如果此处只写return;则返回的是undefined
        } catch (e) {
            return "";//如果此处只写return;则返回的是undefined
        }
    };

    let memberId = getParam(window.location.href, 'memberId')
    let targetId = getParam(window.location.href, 'targetId')
    console.log('memberId', memberId, 'targetId', targetId)
    let commonInfo = {
        memberId,
        targetId,
    }



    let myChatWs = new Websocket();
    function createWebSocket() {
        console.log('建立链接')
        myChatWs.createWebSocket({
            url: "ws://127.0.0.1:8801/",
            socketEventHandle: socketEventHandle,
        });
    }

    window.onload = function () {
        document.querySelector("#btnSend").onclick = function (e) {
            var chatBox = document.getElementById('chatBox').value;

            let senObj = {
                ...commonInfo,
                content: chatBox,
            }
            let sendStr = JSON.stringify(senObj)
            myChatWs.sendMessage(sendStr);
            document.getElementById('chatBox').value = '';
        }

        document.querySelector("#Bridge").onclick = function (e) {
            createWebSocket()
        }
    }

    function onopen() {
        console.log("ws连接成功!" + new Date().toUTCString());
        let senObj = {
            ...commonInfo,
            content: "已经建立连接",
        };
        let sendStr = JSON.stringify(senObj);
        myChatWs.sendMessage(sendStr);
        document.getElementById("Bridge").style.display = "none";
    }

    function onMessageEventFun(message) {
        console.log(message);
        var li = document.createElement("li");
        li.innerHTML = message;
        if (message.indexOf(commonInfo.memberId) > -1) {
            li.setAttribute(
                "style",
                "color: #E91E63;font-weight: 700;text-align: right;"
            );
        } else {
            li.setAttribute("style", "color: #2196F3;font-weight: 700;");
        }
        document.getElementById("chat-list").appendChild(li);
    }

    function socketEventHandle({ type, message }) {
        switch (type) {
            case "onclose":
                break;
            case "onerror":
                break;
            case "onopen":
                onopen();
                break;
            case "sendMessage":
                onMessageEventFun(message);
                break;

            default:
                break;
        }
    }





</script>


</html>

测试的时候先进入项目目录,命令行执行 node chatServer.js 开启node后台服务

客户端用户访问测试地址如下:

http://127.0.0.1:5500/demo/user.html?memberId=1&targetId=2

http://127.0.0.1:5500/demo/user.html?memberId=2&targetId=1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值