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开发微信公众号后台服务实例
Sep 03 NodeJs
Nodejs实现多人同时在线移动鼠标的小游戏分享
Dec 06 NodeJs
NodeJS学习笔记之FS文件模块
Jan 13 NodeJs
nodeJs链接Mysql做增删改查的简单操作
Feb 04 NodeJs
NodeJS、NPM安装配置步骤(windows版本) 以及环境变量详解
May 13 NodeJs
NodeJs使用Mysql模块实现事务处理实例
May 31 NodeJs
NodeJS实现不可逆加密与密码密文保存的方法
Mar 16 NodeJs
nodejs 日志模块winston的使用方法
May 02 NodeJs
Nodejs 和 Electron ubuntu下快速安装过程
May 04 NodeJs
nodejs异步编程基础之回调函数用法分析
Dec 26 NodeJs
NodeJS开发人员常见五个错误理解
Oct 14 NodeJs
Nodejs实现微信分账的示例代码
Jan 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使用number_format函数截取小数的方法分析
2016/05/27 PHP
详解使用php调用微信接口上传永久素材
2017/04/11 PHP
Laravel5.4框架使用socialite实现github登录的方法
2019/03/20 PHP
jQuery调用AJAX时Get和post公用的乱码解决方法实例说明
2013/06/04 Javascript
html+javascript实现可拖动可提交的弹出层对话框效果
2013/08/05 Javascript
js 剪切板应用clipboardData详细解析
2013/12/17 Javascript
jquery validate 自定义验证方法介绍 日期验证
2014/02/27 Javascript
Node.js(安装,启动,测试)
2014/06/09 Javascript
js读取json的两种常用方法示例介绍
2014/10/19 Javascript
Treegrid的动态加载实例代码
2016/04/29 Javascript
Javascript中apply、call、bind的巧妙使用
2016/08/18 Javascript
JavaScript私有变量实例详解
2019/01/24 Javascript
JavaScript 正则应用详解【模式、欲查、反向引用等】
2020/05/13 Javascript
完美解决通过IP地址访问VUE项目的问题
2020/07/18 Javascript
[02:28]DOTA2英雄基础教程 灰烬之灵
2013/12/19 DOTA
[36:22]VP vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[01:00:30]完美世界DOTA2联赛循环赛 Inki vs Matador BO2第二场 10.31
2020/11/02 DOTA
Python Deque 模块使用详解
2014/07/04 Python
python中文编码问题小结
2014/09/28 Python
使用rst2pdf实现将sphinx生成PDF
2016/06/07 Python
Python合并字典键值并去除重复元素的实例
2016/12/18 Python
Python Flask-web表单使用详解
2017/11/18 Python
浅谈python装饰器探究与参数的领取
2017/12/01 Python
对python 各种删除文件失败的处理方式分享
2018/04/24 Python
在python下使用tensorflow判断是否存在文件夹的实例
2019/06/10 Python
python通过nmap扫描在线设备并尝试AAA登录(实例代码)
2019/12/30 Python
h5实现获取用户地理定位的实例代码
2017/07/17 HTML / CSS
Juicy Couture Beauty官方网站:香水和化妆品
2019/03/12 全球购物
了解AppleShare protocol(AppleShare协议)吗
2015/08/28 面试题
医院后勤自我鉴定
2013/10/13 职场文书
自荐信模版
2013/10/24 职场文书
商务英语毕业生自荐信范文
2013/11/08 职场文书
一年级数学上册复习计划
2015/01/17 职场文书
供应商食品安全承诺书
2015/04/29 职场文书
员工试用期工作总结
2019/06/20 职场文书
Python实现信息管理系统
2022/06/05 Python