Nodejs+webSocket搭建多人聊天室


今天花了一个上午的时间去学习了一下使用nodejs+websocket搭建多人聊天室。下面我分享下我做这个多人聊天室案例的整个过程。

先看下最终的效果图

在这里插入图片描述
上图的功能包括:显示在线人数,在同一房间可以互相发送消息,显示在线用户的列表.
下面我讲一步一步的分解我写的这个案例。

准备的东西:

     Nodejs 的基础
     node环境
     熟悉npm的使用
     nodejs-websocket插件
     前端部分用到的websocket一些事件:
     WebSocket 前端部分事件以及方法
     事件处理程序描述
        open	Socket.onopen	连接建立时触发
		message	Socket.onmessage	客户端接收服务端数据时触发
		error	Socket.onerror	通信发生错误时触发
		close	Socket.onclose	连接关闭时触发
		
		WebSocket 方法
		以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:
		
		方法	描述
		Socket.send()	
		使用连接发送数据
		
		Socket.close()	
		关闭连接
		
		举个例子:在建立连接时会出发ws.onopen函数,在收到服务器发来的消息时会自动触发ws.onmessage函数,       
		在用户关闭网页或者手动关闭连接时会触发ws.onclose函数。发送数据的时候使用ws.send函数即可,发送的内
		容作为参数。具体的使用方法在后面会讲到。

        后端部分用到的websocket:
        connect.on('text',callback)
        connect.on('close',callback)
        connect.on('error',callback)

第一步:安装插件并且完善服务端

创建一个js文件命名为app.js
并且进入命令行模式执行 :
安装nodejs-websocke插件

npm install nodejs-websocket --save

app.js文件:

const ws = require('nodejs-websocket');
const htpp = require('http');
//const server = http.createServer();

//封装发送消息的函数(向每个链接的用户发送消息)
const boardcast = (str)=>{
    console.log(str);
  server.connections.forEach((connect)=>{
      connect.sendText(str)
  })
};

//封装获取所有聊天者的nickname
const getAllChatter = ()=>{
      let chartterArr = [];
      server.connections.forEach((connect)=>{
          chartterArr.push({name:connect.nickname})
      });
    return chartterArr;
};

const server = ws.createServer((connect)=>{

     //链接上来的时候
      connect.on('text',(str)=>{
          let data = JSON.parse(str);
          console.log(data);
          switch (data.type)
          {
              case 'setName':
                  connect.nickname = data.nickname;
                  boardcast(JSON.stringify({
                      type:'serverInformation',
                      message:data.nickname+"进入房间",
                  }));

                  boardcast(JSON.stringify({
                      type:'chatterList',
                      list:getAllChatter()
                  }));
                  break;
              case 'chat':
                  boardcast(JSON.stringify({
                      type:'chat',
                      name:connect.nickname,
                      message: data.message
                  }));
                  break;
              default:
                  break;
          }
      });

      //关闭链接的时候
    connect.on('close',()=>{

        //离开房间
        boardcast(JSON.stringify({
            type:'serverInformation',
            message:connect.nickname+'离开房间'
        }));

        //从在线聊天的人数上面除去
        boardcast(JSON.stringify({
            type:'chatterList',
            list: getAllChatter()
        }))
    });

    //错误处理
    connect.on('error',(err)=>{
        console.log(err);
    })

}).listen(3000,()=>{
    console.log("running")
});

这一步写完后启动node服务

第二步 :搭建客户端并与服务端的通信

app.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>小贱贱的多人聊天</title>
    <link rel="stylesheet" href="app.css">
</head>
<body>
    <div class="all">
        <div class = 'person'><text id="onLine">在线人数</text></div>
        <div class="contain">
            <div class="content" id="content"></div>
        </div>
        <div class="footer">
            <input placeholder="设置用户名." name="userName" id="userName"/>
            <button id="setName">设置</button>
            <textarea placeholder="输入您要发送的消息" id="message" name="message"></textarea>
            <button id="sendMessage">发送</button>
        </div>
    </div>

    <div class = "all2">
        <div class="title"><text>在线用户列表:</text></div>
        <div id="userList" class="userList">

        </div>
    </div>
    <script type="text/javascript" language="JavaScript">
        //定义全局的变量
        let ws = null;

        //封装获取时间的函数
        Date.prototype.Format = function (fmt) {
            //author: xjj
            var o = {
                "M+": this.getMonth() + 1, //月份
                "d+": this.getDate(), //日
                "h+": this.getHours(), //小时
                "m+": this.getMinutes(), //分
                "s+": this.getSeconds(), //秒
                "q+": Math.floor((this.getMonth() + 3) / 3), //季度
                "S": this.getMilliseconds() //毫秒
            };
            if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
            for (var k in o)
                if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
            return fmt;
        };

        //封装创建Div并且发送消息的函数
        const createChatDiv = (data)=> {
            let div = document.createElement('div');
            let p_time = document.createElement('p');
            let p_content = document.createElement('p');
            switch (data.type) {
                case 'serverInformation':
                    p_time.innerHTML = new Date().Format("yyyy-MM-dd hh:mm:ss");
                    p_content.innerHTML = data.message;
                    break;
                case  'chat':
                    p_time.innerHTML = new Date().Format("yyyy-MM-dd hh:mm:ss");
                    p_content.innerHTML = data.name+":"+data.message;
                    break;
                default:
                    break;
            }

            p_time.setAttribute('class' ,'time');
            p_content.setAttribute('class','content');

            div.appendChild(p_time);
            div.appendChild(p_content);

            return div;
        };

        //封装发送消息的函数
        const send = ()=>{
            let message = document.getElementById('message');

            //设置不能够发送空消息
            if(!message.value){
                return
            }
            let data = {
                type:'chat',
                message:message.value
            };
            ws.send(JSON.stringify(data));
            message.value = ""
        };

        let setName = document.getElementById('setName');
        setName.onclick = ()=> {
            let userName = document.getElementById('userName');
            let nickName = "我没有起名字";
            if (userName.value) {
                nickName = userName.value;
            }


            //建立连接,并发送连接进入房间(并且连接会一直保存,进行服务端的轮询)
            ws = new WebSocket('ws://127.0.0.1:3000');

            //连接上来的时候
            ws.onopen = () => {
                let data = {
                    type: 'setName',
                    nickname: nickName
                };
                ws.send(JSON.stringify(data))
            };

            //发送消息的时候
           document.getElementById('sendMessage').onclick = ()=>{
                send();
            };


            //当接受服务端的请求的时候
            ws.onmessage = (e) => {
                let data = JSON.parse(e.data);
                 console.log(data);

                //接受的消息为连接的人的个数的时候
                if (data.type === 'chatterList') {
                    let list = data.list;
                    let length = list.length;
                    let userList = document.getElementById('userList');
                    document.getElementById('onLine').innerText = `在线人数${length}人`;

                    for(let i=0;i<list.length;i++){
                        let p_user = document.createElement('p');
                        p_user.setAttribute('class','userList-item');
                        p_user.innerText = list[i].name;
                        userList.appendChild(p_user)
                    }
                }

                //当为接受消息的或者用户进入新房间的时候
                else {
                    let oldContent = document.getElementById('content');
                    oldContent.appendChild(createChatDiv(data))
                }

                  //设置名字不能再改,以及不能改名字
                 setName.setAttribute('disabled',true);
                 let userName = document.getElementById('userName');
                 userName.setAttribute('disabled',true);
                 setName.style.display = "none";

            };

        }

    </script>
</body>
</html>

第三步 :添加CSS样式

app.css文件:

.all{
    width: 400px;
    height: 500px;
    border: 1px dotted grey;
    float: left;
    margin-left: 20px;
}
.person {
    width: 400px;
    height: 50px;
    line-height: 50px;
    text-align: center;
}

.contain {
    width: 400px;
    height: 350px;
}

#content{
    width: 99%;
    height: 100%;
    overflow-y: auto;
}

.footer {
    width: 100%;
    height: 100px;
    border: 1px solid green;
    display: flex;
    flex-direction: row;
    align-items: center;
}
.footer input{
    width: 70px;
    height: 50px;
    float: left;
    margin-right: 5px;
    margin-left: 5px;
    border-radius: 5%;
}
.footer button{
    width: 50px;
    height: 50px;
    float: left;
    background-color: deepskyblue;
    border-radius: 10%;
    margin-right: 5px;
}
.footer textarea{
    width: 200px;
    height: 80px;
    overflow-y: scroll;
    float: left;
    margin-right: 5px;
    border-radius: 5%;
}

/*在线用户的列表*/
.all2{
    width: 150px;
    height: 500px;
    border:1px dotted green;
    float: left;
}

.title{
    width: 150px;
    height:50px;
    line-height: 50px;
    background-color: bisque;
}

.userList{
    overflow-y: scroll;
    height: 450px;
}

第四步:总结

通过本次对,nodejs+websocket的案例,但是这部分是还没关联http的,下次我给大家带来一套关联http的案例,同时本次增加了我对多人聊天室开发方面的认识,同时可能这套代码又一部分小bug,不过希望,不过问题不大,或者喜欢的朋友可以给我点个赞支持我继续写作,谢谢笔芯。

  • 13
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值