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 相关文章推荐
Ubuntu中搭建Nodejs开发环境过程分享
Jun 01 NodeJs
Nodejs学习笔记之Stream模块
Jan 13 NodeJs
nodejs中实现阻塞实例
Mar 24 NodeJs
用nodejs搭建websocket服务器
Jan 23 NodeJs
Nodejs高扩展性的模板引擎 functmpl简介
Feb 13 NodeJs
nodejs中使用HTTP分块响应和定时器示例代码
Mar 19 NodeJs
Nodejs读取文件时相对路径的正确写法(使用fs模块)
Apr 27 NodeJs
NodeJs的fs读写删除移动监听
Apr 28 NodeJs
win系统下nodejs环境安装配置
May 04 NodeJs
nodejs调取微信收货地址的方法
Dec 20 NodeJs
Nodejs实现爬虫抓取数据实例解析
Jul 05 NodeJs
Nodejs技巧之Exceljs表格操作用法示例
Nov 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
第十三节--对象串行化
2006/11/16 PHP
ajax完美实现两个网页 分页功能的实例代码
2013/04/16 PHP
浅谈PHP正则中的捕获组与非捕获组
2016/07/18 PHP
Jvascript学习实践案例(开发常用)
2012/06/25 Javascript
jquery向上向下取整适合分页查询
2014/09/06 Javascript
浅谈JavaScript Array对象
2014/12/29 Javascript
jQuery实现批量判断表单中文本框非空的方法(2种方法)
2015/12/09 Javascript
JS Ajax请求如何防止重复提交
2016/06/13 Javascript
javascript 中模板方法单例的实现方法
2017/10/17 Javascript
js尾调用优化的实现
2019/05/23 Javascript
CKeditor4 字体颜色功能配置方法教程
2019/06/26 Javascript
Vue通过for循环随机生成不同的颜色或随机数的实例
2019/11/09 Javascript
[02:49]2018DOTA2亚洲邀请赛主赛事决赛日战况回顾 Mineski鏖战5局夺得辉耀
2018/04/10 DOTA
python遍历目录的方法小结
2016/04/28 Python
Python字符串拼接六种方法介绍
2017/12/18 Python
Python数据类型之List列表实例详解
2019/05/08 Python
python 在某.py文件中调用其他.py内的函数的方法
2019/06/25 Python
keras获得某一层或者某层权重的输出实例
2020/01/24 Python
keras 两种训练模型方式详解fit和fit_generator(节省内存)
2020/07/03 Python
python字典通过值反查键的实现(简洁写法)
2020/09/30 Python
详解python百行有效代码实现汉诺塔小游戏(简约版)
2020/10/30 Python
html5视频播放_动力节点Java学院整理
2017/07/13 HTML / CSS
HTML5实现的震撼3D焦点图动画的示例代码
2019/09/26 HTML / CSS
澳大利亚婴儿喂养品牌:Cherub Baby
2018/11/01 全球购物
PatPat阿根廷:妈妈们的购物平台
2019/05/30 全球购物
澳大利亚网上书店:QBD
2021/01/09 全球购物
预备党员思想汇报
2014/01/08 职场文书
《纸船和风筝》教学反思
2014/02/15 职场文书
目标责任书范文
2014/04/14 职场文书
反邪教警示教育方案
2014/05/13 职场文书
护士求职信范文
2014/05/24 职场文书
银行青年文明号事迹材料
2014/05/31 职场文书
国土资源局开展党的群众路线教育实践活动整改措施
2014/09/26 职场文书
朋友离别感言
2015/08/04 职场文书
golang interface判断为空nil的实现代码
2021/04/24 Golang
Python面向对象之成员相关知识总结
2021/06/24 Python