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中exports与module.exports的区别详细介绍
Jan 14 NodeJs
使用Nodejs开发微信公众号后台服务实例
Sep 03 NodeJs
nodejs实现HTTPS发起POST请求
Apr 23 NodeJs
你一定会收藏的Nodejs代码片段
Feb 04 NodeJs
nodejs连接mongodb数据库实现增删改查
Dec 01 NodeJs
用nodeJS搭建本地文件服务器的几种方法小结
Mar 16 NodeJs
nodejs 日志模块winston的使用方法
May 02 NodeJs
nodeJs爬虫的技术点总结
May 13 NodeJs
Mac下通过brew安装指定版本的nodejs教程
May 17 NodeJs
NodeJS如何实现同步的方法示例
Aug 24 NodeJs
nodejs中方法和模块用法示例
Dec 24 NodeJs
nodejs脚本centos开机启动实操方法
Mar 04 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 无线电
php include加载文件两种方式效率比较
2010/08/08 PHP
smarty模板引擎从配置文件中获取数据的方法
2015/01/22 PHP
php字符串替换函数substr_replace()用法实例
2015/03/17 PHP
PHP设计模式之工厂模式与单例模式
2016/09/28 PHP
PHP在linux上执行外部命令的方法
2017/02/06 PHP
PHP扩展安装方法步骤解析
2020/11/24 PHP
document.createElement()用法
2013/03/13 Javascript
JS禁用浏览器退格键实现思路及代码
2013/10/29 Javascript
三种动态加载js的jquery实例代码另附去除js方法
2014/04/30 Javascript
jQuery使用andSelf()来包含之前的选择集
2014/05/19 Javascript
jQuery异步获取json数据方法汇总
2014/12/22 Javascript
使用requestAnimationFrame实现js动画性能好
2015/08/06 Javascript
js实现带缓冲效果的仿QQ面板折叠菜单代码
2015/09/06 Javascript
JavaScript如何实现对数字保留两位小数一位自动补零
2015/12/18 Javascript
解决jQuery ajax请求在IE6中莫名中断的问题
2016/06/20 Javascript
ion content 滚动到底部会遮住一部分视图的快速解决方法
2016/09/06 Javascript
jQuery中的100个技巧汇总
2016/12/15 Javascript
Canvas实现动态的雪花效果
2017/02/13 Javascript
老生常谈Bootstrap媒体对象
2017/07/06 Javascript
vue增加强缓存和版本号的实现方法
2019/05/01 Javascript
浅谈Vue使用Elementui修改默认的最快方法
2020/12/05 Vue.js
CentOS 8.2服务器上安装最新版Node.js的方法
2020/12/16 Javascript
ZABBIX3.2使用python脚本实现监控报表的方法
2019/07/02 Python
解决Django删除migrations文件夹中的文件后出现的异常问题
2019/08/31 Python
没编程基础可以学python吗
2020/06/17 Python
详解pandas apply 并行处理的几种方法
2021/02/24 Python
澳大利亚家庭花园和DIY工具网店:VidaXL
2019/05/03 全球购物
汽车销售求职自荐信
2013/10/01 职场文书
应届生求职简历的自我评价怎么写
2013/10/23 职场文书
上级检查欢迎词
2014/01/18 职场文书
投标承诺书范本
2014/03/27 职场文书
学校周年庆活动方案
2014/08/22 职场文书
绿色环保家庭事迹材料
2014/08/31 职场文书
忠诚奉献演讲稿
2014/09/12 职场文书
南京市纪委监察局整改方案
2014/09/16 职场文书