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服务器(9):实现非阻塞操作
Dec 18 NodeJs
NodeJS与HTML5相结合实现拖拽多个文件上传到服务器的实现方法
Jul 26 NodeJs
Nodejs进阶:express+session实现简易登录身份认证
Apr 24 NodeJs
nodejs操作mysql实现增删改查的实例
May 28 NodeJs
nodejs Assert中equal(),strictEqual(),deepEqual(),strictDeepEqual()比较
Sep 18 NodeJs
nodejs实现爬取网站图片功能
Dec 14 NodeJs
NodeJS安装图文教程
Apr 19 NodeJs
nodejs前端模板引擎swig入门详解
May 15 NodeJs
对mac下nodejs 更新到最新版本的最新方法(推荐)
May 17 NodeJs
Nodejs核心模块之net和http的使用详解
Apr 02 NodeJs
用Nodejs实现在终端中炒股的实现
Oct 18 NodeJs
详解nodejs内置模块
May 06 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
历史证明,懒惰才是推动科学发展技术进步的动力
2021/03/02 无线电
解析使用ThinkPHP应该掌握的调试手段
2013/06/20 PHP
PHP获取QQ达人QQ信息的方法
2015/03/05 PHP
codeigniter中view通过循环显示数组数据的方法
2015/03/20 PHP
WordPress伪静态规则设置代码实例
2020/12/10 PHP
showModelessDialog()使用详解
2006/09/21 Javascript
javascript 动态参数判空操作
2008/12/22 Javascript
Jquery插件 easyUI属性汇总
2011/01/19 Javascript
用JSON做数据传输格式中的一些问题总结
2011/12/21 Javascript
JavaScript可否多线程? 深入理解JavaScript定时机制
2012/05/23 Javascript
Jquery index()方法 获取相应元素索引值
2012/10/12 Javascript
JS中Iframe之间传值及子页面与父页面应用
2013/03/11 Javascript
使用typeof判断function是否存在于上下文
2014/08/14 Javascript
使用 js+正则表达式为关键词添加链接
2014/11/11 Javascript
ztree获取当前选中节点子节点id集合的方法
2015/02/12 Javascript
javascript多物体运动实现方法分析
2016/01/08 Javascript
JavaScript中数组添加值和访问值常见问题
2016/02/06 Javascript
jQuery表单验证插件解析(推荐)
2016/07/21 Javascript
AngularJS 模块详解及简单实例
2016/07/28 Javascript
jQuery如何解决IE输入框不能输入的问题
2016/10/08 Javascript
Angularjs的启动过程分析
2017/07/18 Javascript
vue中使用echarts制作圆环图的实例代码
2018/07/27 Javascript
关于引入vue.js 文件的知识点总结
2020/01/28 Javascript
js页面加载后执行的几种方式小结
2020/01/30 Javascript
vue自动添加浏览器兼容前后缀操作
2020/08/13 Javascript
解决element-ui的下拉框有值却无法选中的情况
2020/11/07 Javascript
详解ES6 扩展运算符的使用与注意事项
2020/11/12 Javascript
Python 二叉树的层序建立与三种遍历实现详解
2019/07/29 Python
Python简易计算器制作方法代码详解
2019/10/31 Python
Django之腾讯云短信的实现
2020/06/12 Python
使用canvas压缩图片大小的方法示例
2019/08/02 HTML / CSS
校园学雷锋活动月总结
2014/03/09 职场文书
单位员工收入证明样本
2014/10/09 职场文书
门市房租房协议书
2014/12/04 职场文书
了解Redis常见应用场景
2021/06/23 Redis
Java实现多线程聊天室
2021/06/26 Java/Android