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+express+html5 实现拖拽上传
Aug 08 NodeJs
NodeJS制作爬虫全过程(续)
Dec 22 NodeJs
Nodejs多站点切换Htpps协议详解及简单实例
Feb 23 NodeJs
nodejs入门教程六:express模块用法示例
Apr 24 NodeJs
详解NODEJS的http实现
Jan 04 NodeJs
nodejs(officegen)+vue(axios)在客户端导出word文档的方法
Jul 31 NodeJs
nodejs基础之buffer缓冲区用法分析
Dec 26 NodeJs
nodejs log4js 使用详解
May 31 NodeJs
详解NodeJs项目 CentOs linux服务器线上部署
Sep 16 NodeJs
nodeJS与MySQL实现分页数据以及倒序数据
Jun 05 NodeJs
nodejs中使用worker_threads来创建新的线程的方法
Jan 22 NodeJs
分享五个Node.js开发的优秀实践 
Apr 07 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实现和c#一致的DES加密解密实例
2017/07/24 PHP
php实现快速对二维数组某一列进行组装的方法小结
2019/12/04 PHP
js跟随滚动条滚动浮动代码
2009/12/31 Javascript
Javascript学习笔记 delete运算符
2011/09/13 Javascript
js data日期初始化的5种方法
2013/12/29 Javascript
解决html按钮切换绑定不同函数后点击时执行多次函数问题
2014/05/14 Javascript
JS清除字符串中重复值的实现方法
2016/08/03 Javascript
AngularJS中update两次出现$promise属性无法识别的解决方法
2017/01/05 Javascript
vue2组件实现懒加载浅析
2017/03/29 Javascript
jQuery实现的电子时钟效果完整示例
2018/04/28 jQuery
JavaScript callback回调函数用法实例分析
2018/05/08 Javascript
解决Mac安装thrift因bison报错的问题
2018/05/17 Javascript
浅谈React碰到v-if
2018/11/04 Javascript
JS实现checkbox互斥(单选)功能示例
2019/05/04 Javascript
Python创建文件和追加文件内容实例
2014/10/21 Python
在Python中处理字符串之ljust()方法的使用简介
2015/05/19 Python
各个系统下的Python解释器相关安装方法
2015/10/12 Python
Python实现对象转换为xml的方法示例
2017/06/08 Python
Python3.5编程实现修改IIS WEB.CONFIG的方法示例
2017/08/18 Python
python处理两种分隔符的数据集方法
2018/12/12 Python
Django如何将URL映射到视图
2019/07/29 Python
pytorch使用指定GPU训练的实例
2019/08/19 Python
Python实现微信机器人的方法
2019/09/06 Python
基于python cut和qcut的用法及区别详解
2019/11/22 Python
Python Numpy 控制台完全输出ndarray的实现
2020/02/19 Python
css3 自定义字体font-face使用介绍
2014/05/14 HTML / CSS
巴西最大的体育用品商城:Netshoes巴西
2016/11/29 全球购物
教师自我鉴定范文
2013/11/10 职场文书
道德大讲堂实施方案
2014/05/14 职场文书
法院个人总结
2015/03/03 职场文书
2015年社区居委会工作总结
2015/05/18 职场文书
代理词怎么写
2015/05/25 职场文书
Python 文本滚动播放器的实现代码
2021/04/25 Python
Python数据分析入门之数据读取与存储
2021/05/13 Python
python实现局部图像放大
2021/11/17 Python
Android 界面一键变灰 深色主题工具类
2022/04/28 Java/Android