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 实现模拟form表单上传文件
Jul 14 NodeJs
轻松创建nodejs服务器(4):路由
Dec 18 NodeJs
Nodejs中调用系统命令、Shell脚本和Python脚本的方法和实例
Jan 01 NodeJs
Nodejs关于gzip/deflate压缩详解
Mar 04 NodeJs
Nodejs进阶:如何将图片转成datauri嵌入到网页中去实例
Nov 21 NodeJs
详解Nodejs的timers模块
Dec 22 NodeJs
nodejs基础知识
Feb 03 NodeJs
nodejs中安装ghost出错的原因及解决方法
Oct 23 NodeJs
nodejs结合Socket.IO实现的即时通讯功能详解
Jan 12 NodeJs
NodeJS简单实现WebSocket功能示例
Feb 10 NodeJs
详解NodeJs项目 CentOs linux服务器线上部署
Sep 16 NodeJs
使用nodejs实现JSON文件自动转Excel的工具(推荐)
Jun 24 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保存信息到当前Session的方法
2015/03/16 PHP
php获取访问者IP地址汇总
2015/04/24 PHP
PHP新特性之字节码缓存和内置服务器
2017/08/11 PHP
YII框架常用技巧总结
2019/04/27 PHP
js onkeypress与onkeydown 事件区别详细说明
2012/12/13 Javascript
javascript禁用Tab键脚本实例
2013/11/22 Javascript
浅谈javascript中createElement事件
2014/12/05 Javascript
ANGULARJS中用NG-BIND指令实现单向绑定的例子
2014/12/08 Javascript
jQuery实现模仿微博下拉滚动条加载数据效果
2015/12/25 Javascript
JavaScript简单生成 N~M 之间随机数的方法
2017/01/13 Javascript
数组Array的排序sort方法
2017/02/17 Javascript
AngularJS路由切换实现方法分析
2017/03/17 Javascript
基于ES6 Array.of的用法(实例讲解)
2017/09/05 Javascript
NodeJs 文件系统操作模块fs使用方法详解
2018/11/26 NodeJs
Angular2 自定义表单验证器的实现方法
2018/12/14 Javascript
vue使用recorder.js实现录音功能
2019/11/22 Javascript
JavaScript实现指定数量的并发限制的示例代码
2020/03/10 Javascript
[01:33]一分钟玩转DOTA2第三弹:DOTA2&DotA快捷操作大对比
2014/06/04 DOTA
Python中MYSQLdb出现乱码的解决方法
2014/10/11 Python
开始着手第一个Django项目
2015/07/15 Python
Python 3实战爬虫之爬取京东图书的图片详解
2017/10/09 Python
Python读取图片为16进制表示简单代码
2018/01/19 Python
Python实现查看系统启动项功能示例
2018/05/10 Python
python多进程使用及线程池的使用方法代码详解
2018/10/24 Python
python 将列表里的字典元素合并为一个字典实例
2020/09/01 Python
前后端结合实现amazeUI分页效果
2020/08/21 HTML / CSS
教育科研先进个人材料
2014/01/26 职场文书
超市促销活动方案
2014/03/05 职场文书
办公室打字员岗位职责
2014/04/16 职场文书
纪念九一八事变演讲稿1000字
2014/09/14 职场文书
2014年企业员工工作总结
2014/12/09 职场文书
优秀党员先进材料
2014/12/18 职场文书
校运会广播稿
2015/08/19 职场文书
JavaScript文档对象模型DOM
2021/11/20 Javascript
win10电脑老是死机怎么办?win10系统老是死机的解决方法
2022/08/05 数码科技
win11怎么消除图标小盾牌?win11消除图标小盾牌解决方法
2022/08/05 数码科技