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 26 NodeJs
轻松创建nodejs服务器(5):事件处理程序
Dec 18 NodeJs
nodejs实现获取当前url地址及url各种参数值
Jun 25 NodeJs
详解nodejs微信公众号开发——6.自定义菜单
Apr 13 NodeJs
Nodejs 复制文件/文件夹的方法
Aug 24 NodeJs
NodeJS爬虫实例之糗事百科
Dec 14 NodeJs
webpack打包nodejs项目的方法
Sep 26 NodeJs
NodeJS读取分析Nginx错误日志的方法
May 14 NodeJs
NodeJs实现简易WEB上传下载服务器
Aug 10 NodeJs
Nodejs + Websocket 指定发送及群聊的实现
Jan 09 NodeJs
通过实例了解Nodejs模块系统及require机制
Jul 16 NodeJs
Nodejs + sequelize 实现增删改查操作
Nov 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序列化函数serialize() 和 unserialize() 与原生函数对比
2015/05/08 PHP
php源码分析之DZX1.5加密解密函数authcode用法
2015/06/17 PHP
PHP比较运算符的详细介绍
2015/09/29 PHP
PHP生成制作验证码的简单实例
2016/06/12 PHP
php生成0~1随机小数的方法(必看)
2017/04/05 PHP
PHP接口继承及接口多继承原理与实现方法详解
2017/10/18 PHP
过虑特殊字符输入的js代码
2010/08/05 Javascript
jquery判断元素的子元素是否存在的示例代码
2014/02/04 Javascript
node.js中的fs.lchownSync方法使用说明
2014/12/16 Javascript
javaScript中push函数用法实例分析
2015/06/08 Javascript
CSS或者JS实现鼠标悬停显示另一元素
2016/01/22 Javascript
js基于myFocus实现轮播图效果
2017/02/14 Javascript
快速掌握jquery分页插件jqPaginator的使用方法
2017/08/09 jQuery
React Native验证码倒计时工具类分享
2017/10/24 Javascript
使用Angular CLI快速创建Angular项目的一些基本概念和写法小结
2018/04/22 Javascript
Vue组件中的data必须是一个function的原因浅析
2018/09/03 Javascript
利用Promise自定义一个GET请求的函数示例代码
2019/03/20 Javascript
Vue实现base64编码图片间的切换功能
2019/12/04 Javascript
JS+DIV实现拖动效果
2020/02/11 Javascript
js实现带有动画的返回顶部
2020/08/09 Javascript
[48:21]林俊杰圣堂刺客超神杀戮秀
2014/10/29 DOTA
python 追踪except信息方式
2020/04/25 Python
使用pymysql查询数据库,把结果保存为列表并获取指定元素下标实例
2020/05/15 Python
Django nginx配置实现过程详解
2020/09/10 Python
PIP和conda 更换国内安装源的方法步骤
2020/09/21 Python
使用CSS3的ruby-position固定注音位置的用法示例
2016/07/05 HTML / CSS
简单的HTML5初步入门教程
2015/09/29 HTML / CSS
会议活动邀请函
2014/01/27 职场文书
母亲节感恩寄语
2014/02/21 职场文书
幼儿园家长评语大全
2014/04/16 职场文书
电工技术比武方案
2014/05/11 职场文书
高中军训的心得体会
2014/09/01 职场文书
小学运动会报道稿
2014/10/04 职场文书
TV动画《间谍过家家》公开PV
2022/03/20 日漫
详解Vue3使用axios的配置教程
2022/04/29 Vue.js
如何基于python实现单目三维重建详解
2022/06/25 Python