nodejs实现的一个简单聊天室功能分享


Posted in NodeJs onDecember 06, 2014

今天我来实现一个简单的聊天室,后台用nodejs, 客户端与服务端通信用socket.io,这是一个比较成熟的websocket框架.

初始工作

1.安装express, 用这个来托管socket.io,以及静态页面,命令npm install express --save,--save可以使包添加到package.json文件里.
2.安装socket.io,命令npm install socket.io --save.

编写服务端代码

首先我们通过express来托管网站,并附加到socket.io实例里,因为socket.io初次连接需要http协议

var express = require('express'),

    io = require('socket.io');
var app = express();
app.use(express.static(__dirname));
var server = app.listen(8888);


var ws = io.listen(server);

添加服务器连接事件,当客户端连接成功之后,发公告告诉所有在线用户,并且,当用户发送消息时,发广播通知其它用户.
ws.on('connection', function(client){

    console.log('\033[96msomeone is connect\033[39m \n');

    client.on('join', function(msg){

        // 检查是否有重复

        if(checkNickname(msg)){

            client.emit('nickname', '昵称有重复!');

        }else{

            client.nickname = msg;

            ws.sockets.emit('announcement', '系统', msg + ' 加入了聊天室!');

        }

    });

    // 监听发送消息

    client.on('send.message', function(msg){

        client.broadcast.emit('send.message',client.nickname,  msg);

    });

    // 断开连接时,通知其它用户

    client.on('disconnect', function(){

        if(client.nickname){

            client.broadcast.emit('send.message','系统',  client.nickname + '离开聊天室!');

        }

    })
})

由于客户端是通过昵称来标识的,所以服务端需要一个检测昵称重复的函数

// 检查昵称是否重复

var checkNickname = function(name){

    for(var k in ws.sockets.sockets){

        if(ws.sockets.sockets.hasOwnProperty(k)){

            if(ws.sockets.sockets[k] && ws.sockets.sockets[k].nickname == name){

                return true;

            }

        }

    }

    return false;

}

编写客服端代码

由于服务端采用第三方websokcet框架,所以前端页面需要单独引用socket.io客户端代码,源文件可以从socket.io模块里找,windows下路径为node_modules\socket.io\node_modules\socket.io-client\dist,这里有开发版和压缩版的,默认引用开发版就行.

前端主要处理输入昵称检查,消息处理,完整代码如下:

<!DOCTYPE html>

<html>

<head>

    <title>socket.io 聊天室例子</title>

    <meta charset="utf-8">

    <link rel="stylesheet" href="css/reset.css"/>

    <link rel="stylesheet" href="css/bootstrap.css"/>

    <link rel="stylesheet" href="css/app.css"/>

</head>

<body>

    <div class="wrapper">

         <div class="content" id="chat">

             <ul id="chat_conatiner">

             </ul>

         </div>

         <div class="action">

             <textarea ></textarea>

             <button class="btn btn-success" id="clear">清屏</button>

             <button class="btn btn-success" id="send">发送</button>

         </div>

    </div>

    <script type="text/javascript" src="js/socket.io.js"></script>

    <script type="text/javascript">
          var ws = io.connect('http://172.16.2.184:8888');

          var sendMsg = function(msg){

              ws.emit('send.message', msg);

          }

          var addMessage = function(from, msg){

              var li = document.createElement('li');

              li.innerHTML = '<span>' + from + '</span>' + ' : ' + msg;

              document.querySelector('#chat_conatiner').appendChild(li);
              // 设置内容区的滚动条到底部

              document.querySelector('#chat').scrollTop = document.querySelector('#chat').scrollHeight;
              // 并设置焦点

              document.querySelector('textarea').focus();
          }
          var send = function(){

              var ele_msg = document.querySelector('textarea');

              var msg = ele_msg.value.replace('\r\n', '').trim();

              console.log(msg);

              if(!msg) return;

              sendMsg(msg);

              // 添加消息到自己的内容区

              addMessage('你', msg);

              ele_msg.value = '';

          }
          ws.on('connect', function(){

              var nickname = window.prompt('输入你的昵称!');

              while(!nickname){

                  nickname = window.prompt('昵称不能为空,请重新输入!')

              }

              ws.emit('join', nickname);

          });
          // 昵称有重复

          ws.on('nickname', function(){

              var nickname = window.prompt('昵称有重复,请重新输入!');

              while(!nickname){

                  nickname = window.prompt('昵称不能为空,请重新输入!')

              }

              ws.emit('join', nickname);

          });
          ws.on('send.message', function(from, msg){

              addMessage(from, msg);

          });
          ws.on('announcement', function(from, msg){

              addMessage(from, msg);

          });
          document.querySelector('textarea').addEventListener('keypress', function(event){

              if(event.which == 13){

                  send();

              }

          });

          document.querySelector('textarea').addEventListener('keydown', function(event){

              if(event.which == 13){

                  send();

              }

          });

          document.querySelector('#send').addEventListener('click', function(){

              send();

          });
          document.querySelector('#clear').addEventListener('click', function(){

              document.querySelector('#chat_conatiner').innerHTML = '';

          });

    </script>

</body>

</html>

这里提供完整的代码压缩文件

总结

nodejs是一个好东西,尤其是在处理消息通讯,网络编程方面,天生的异步IO.

NodeJs 相关文章推荐
NodeJS与Mysql的交互示例代码
Aug 18 NodeJs
轻松创建nodejs服务器(2):nodejs服务器的构成分析
Dec 18 NodeJs
async/await与promise(nodejs中的异步操作问题)
Mar 03 NodeJs
nodejs根据ip数组在百度地图中进行定位
Mar 06 NodeJs
深入nodejs中流(stream)的理解
Mar 27 NodeJs
nodejs和C语言插入mysql数据库乱码问题的解决方法
Apr 14 NodeJs
nodejs实现截取上传视频中一帧作为预览图片
Dec 10 NodeJs
详解nodejs 开发企业微信第三方应用入门教程
Mar 12 NodeJs
nodejs实现用户登录路由功能
May 22 NodeJs
Nodejs异步流程框架async的方法
Jun 07 NodeJs
NodeJs 模仿SIP话机注册的方法
Jun 21 NodeJs
Nodejs实现WebSocket代码实例
May 19 NodeJs
详谈nodejs异步编程
Dec 04 #NodeJs
nodejs下打包模块archiver详解
Dec 03 #NodeJs
nodejs中转换URL字符串与查询字符串详解
Nov 26 #NodeJs
nodejs教程之制作一个简单的文章发布系统
Nov 21 #NodeJs
nodejs教程之环境安装及运行
Nov 21 #NodeJs
nodejs教程之异步I/O
Nov 21 #NodeJs
nodejs教程之入门
Nov 21 #NodeJs
You might like
php的一个简单加密解密代码
2014/01/14 PHP
PHP开发注意事项总结
2015/02/04 PHP
两种php实现图片上传的方法
2016/01/22 PHP
微信小程序 消息推送php服务器验证实例详解
2017/03/30 PHP
详谈phpAdmin修改密码后拒绝访问的问题
2017/04/03 PHP
PHP中散列密码的安全性分析
2019/07/26 PHP
如何在PHP中生成随机数
2020/06/04 PHP
基于逻辑运算的简单权限系统(实现) JS 版
2007/03/24 Javascript
Javascript base64编码实现代码
2011/12/02 Javascript
javascript学习笔记(六)数据类型和JSON格式
2014/10/08 Javascript
javascript实现图片左右滚动效果【可自动滚动,有左右按钮】
2016/09/19 Javascript
微信小程序 闭包写法详细介绍
2016/12/14 Javascript
单击按钮发送验证码,出现倒计时的简单实例
2017/03/17 Javascript
关于Node.js中Buffer的一些你可能不知道的用法
2017/03/28 Javascript
Javascript别踩白块儿(钢琴块儿)小游戏实现代码
2017/07/20 Javascript
关于Vue在ie10下空白页的debug小结
2018/05/02 Javascript
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
2018/12/06 jQuery
Three.JS实现三维场景
2018/12/30 Javascript
VUE注册全局组件和局部组件过程解析
2019/10/10 Javascript
Vue-cli打包后如何本地查看的操作
2020/09/02 Javascript
[04:53]DOTA2英雄基础教程 祈求者
2014/01/03 DOTA
[00:31]DOTA2荣耀之路7:Miracle-空血无敌斩
2018/05/31 DOTA
用python删除java文件头上版权信息的方法
2014/07/31 Python
调试Python程序代码的几种方法总结
2015/04/28 Python
使用Python操作FTP实现上传和下载的方法
2019/04/01 Python
Python多进程入门、分布式进程数据共享实例详解
2019/06/03 Python
python视频按帧截取图片工具
2019/07/23 Python
Python unittest如何生成HTMLTestRunner模块
2020/09/08 Python
用 python 进行微信好友信息分析
2020/11/28 Python
世界上第一个水枕头:Mediflow
2018/12/06 全球购物
安全生产一岗双责责任书
2014/07/28 职场文书
学生穿着不得体检讨书
2014/10/12 职场文书
材料采购员岗位职责
2015/04/03 职场文书
爱心捐赠活动简讯
2015/07/20 职场文书
2016年元旦致辞
2015/08/01 职场文书
css清除浮动clearfix:after的用法详解(附完整代码)
2023/05/21 HTML / CSS