这不是一个项目而是一个适合刚開始学习的人学习的样例。主要实现了下面基本功能:

1:群聊。每个人都能够收到其它人的消息,以及能够发消息给其它人,每个人用ip地址标识。

2:显示当前在线用户。

3:每个用户登入登出。其它人都能够看到。

4:每个用户能够看到其它人是否正在输入消息。

实现方式没有选择低效的轮询方式,而是採用基于websocket协议的socket.io模块,websocket协议同意在client与服务端之间建立一个全双工的通信通道。因此服务端能够主动推消息给client。相比传统的轮询,实时性更好。

前端代码例如以下:

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <title>Socket.IO chat</title>
  5. <style>
  6. * { margin: 0; padding: 0; box-sizing: border-box; }
  7. body { font: 13px Helvetica, Arial; }
  8. form { background: #fc5bff; padding: 2px; position: fixed; bottom: 0; width: 100%; }
  9. form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
  10. form button { width: 9%; background: rgb(217, 222, 221); border: none; padding: 10px; }
  11. #messages { list-style-type: none; margin: 0; padding: 0; }
  12. #messages li { padding: 5px 10px; }
  13. #messages li:nth-child(odd) { background: #eee; }
  14. </style>
  15. </head>
  16. <body>
  17. <ul id="messages"></ul>
  18. <ul><li id='typingshow'></li></ul>
  19. <div id='joinshow'></div>
  20. <div id='leftshow'></div>
  21. <div id='onlineshow'></div>
  22. <form action="">
  23.  
  24. <input id="m" autocomplete="off" /><button id='btn'>Send</button>
  25. </form>
  26. <script src="jquery-1.10.2.min.js"></script>
  27. <script src="/socket.io/socket.io.js"></script>
  28. <script>
  29. var socket = io();
  30. var typingIps={};
  31. var typing=false;
  32. var lastTypingTime;
  33. function updateTyping() {
  34. if (!typing) {
  35. typing = true;
  36. socket.emit('typing');
  37. }
  38. lastTypingTime = (new Date()).getTime();
  39.  
  40. setTimeout(function () {
  41. var typingTimer = (new Date()).getTime();
  42. var timeDiff = typingTimer - lastTypingTime;
  43. if (timeDiff >= 400 && typing) {
  44. socket.emit('stop typing');
  45. typing = false;
  46. }
  47. }, 400);
  48. }
  49. $('form').submit(function(){
  50. socket.emit('chat message',$('#m').val());
  51. socket.emit('stop typing');
  52. typing = false;
  53. $('#m').val('');
  54. return false;
  55. });
  56. $('#m').keyup(function(){
  57. updateTyping();
  58. });
  59. socket.on('online num',function(msg){
  60. $('#onlineshow').text('当前在线'+msg+'人');
  61. });
  62.  
  63. socket.on('join', function (msg) {
  64. $('#joinshow').text(msg.ip+'增加');
  65. });
  66. socket.on('typing',function(msg){
  67. typingIps[msg.ip]=msg.ip;
  68. var typingArr=[];
  69. for(var ip in typingIps){
  70. typingArr.push(typingIps[ip]);
  71. }
  72. $('#typingshow').text(typingArr.join(',') + '正在输入...');
  73. });
  74. socket.on('stop typing',function(msg){
  75. delete typingIps[msg.ip];
  76. var typingArr=[];
  77. for(var ip in typingIps){
  78. typingArr.push(typingIps[ip]);
  79. }
  80. if(typingArr.length===0){
  81. $('#typingshow').text('');
  82. }else{
  83. $('#typingshow').text(typingArr.join(',') + '正在输入...');
  84. }
  85. });
  86. socket.on('chat message', function(msg){
  87. $('#messages').append($('<li>').text(msg.ip+'说:'+msg.content));
  88. });
  89. socket.on('user left', function(msg){
  90. $('#leftshow').text(msg.ip+'离开了');
  91. $('#onlineshow').text('当前在线'+msg.onlineNum+'人');
  92. });
  93. </script>
  94. </body>
  95. </html>

服务端代码:

  1. /**
  2. * Created by luzhen on 14-11-10.
  3. */
  4. var express = require('express');
  5. var app=express();
  6. var http = require('http').Server(app);
  7. var io = require('socket.io')(http);
  8. var ips={};
  9. app.use(express.static(__dirname + '/public'));
  10. app.get('/', function (req, res) {
  11. res.sendFile(__dirname + '/index.html');
  12. });
  13. var onlineNum=0;
  14. io.on('connection', function (socket) {
  15. console.log(socket.request.connection.remoteAddress);
  16. ips[socket.request.connection.remoteAddress]=socket.request.connection.remoteAddress;//clientip
  17. //socket.handshake.address 服务端ip
  18. onlineNum++;
  19. socket.broadcast.emit('join', {'ip':socket.request.connection.remoteAddress});//广播新用户增加
  20.  
  21. io.emit('online num',onlineNum);//广播当前在线人数
  22.  
  23. socket.on('chat message', function (msg) {
  24. io.emit('chat message', {ip:socket.request.connection.remoteAddress,'content':msg});
  25. console.log('message: ' + msg);
  26. });
  27.  
  28. socket.on('typing', function (msg) {
  29. socket.broadcast.emit('typing', {'ip':socket.request.connection.remoteAddress});
  30. });
  31. socket.on('stop typing', function (msg) {
  32. socket.broadcast.emit('stop typing', {'ip':socket.request.connection.remoteAddress});
  33. });
  34.  
  35. socket.on('disconnect',function(){
  36. delete ips[socket.request.connection.remoteAddress];
  37. onlineNum--;
  38. socket.broadcast.emit('user left', {'ip':socket.request.connection.remoteAddress,'onlineNum':onlineNum});
  39. });
  40. });
  41.  
  42. http.listen(3000, function () {
  43. console.log('listening on *:3000');
  44. });

新增了防止刷屏功能,完整代码开源在GitHub上。

Demo演示 查看效果

nodejs实如今线群聊的更多相关文章

  1. 怎样实如今Windows下编写的代码,直接在Linux下编译

    方法一: 怎样实如今Windows7下编写Linux程序.写完程序以后.不用复制文件,直接在Linux(RHEL6.5)机器上编译最新的代码. 1.首先将Windows的代码目录设置为共享目录: 2. ...

  2. socket.io实现在线群聊

    我自己在用socket.io开发,对官方网站上的文档,进行简单的整理,然后自己写了一个简单的聊天程序.最最开始 先安装socket.io: npm install socket.io 利用Node的搭 ...

  3. @font-face(css3属性)实如今网页中嵌入随意字体

    @font-face语法规则 @font-face { font-family: <YourWebFontName>; src: <source> [<format> ...

  4. WebView调用有道词典实如今线查词

        WebView(网络视图)能载入显示网页,能够将其视为一个浏览器.它使用了WebKit渲染引擎载入显示网页,用法非常easy,直接在XML文件里写入webview控件就可以,主要代码例如以下: ...

  5. Android使用有道翻译API实如今线翻译功能

    在Android应用中,加入在线翻译的功能,这里调用的是有道翻译的API. 使用有道翻译API.首先要申请一个key,申请地址为:path=data-mode">有道翻译API申请地址 ...

  6. NodeJS系列~第四个小例子,NodeJs处理Get请求和Post请求

    返回目录 说在前 对于HTTP请求来说,我们通常使用的是Get和Post,除此之外还有put,delete等,而对于get来说,比较lightweight,只是对字符串的传输,它会被添加到URL地址里 ...

  7. nodejs具体解释

    文件夹 javascript与node.js     javascript与你     因为javascript真正意义上有两种,甚至能够说是三种形态(从最早的作为DHTML进行增强的小工具,到像jQ ...

  8. 开源server软件

    Java缓存server jmemcached http://www.oschina.net/p/jmemcached jmemcached 是一个Java版的 memcached 缓存server, ...

  9. Android面试题收集(有具体答案)

    Android面试题目及其答案 1.Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念 DVM指dalivk的虚拟机.每个Android应用程序都在它自己的进程中执行,都 ...

随机推荐

  1. eclipse在linux下无故闪退解决

    A fatal error has been detected by the Java Runtime Environment: SIGSEGV (0xb) at pc=0x00007f25d0b92 ...

  2. Java学习之路(3)

    JKD的安装和配置: 一.适合超级菜鸟的,不用设置系统路径,不用到处找插件 (1)如果你的系统是windows或linux,根据系统的不同(32位和64位之分),先到www.baidu.com搜索jd ...

  3. linux解决无法打开资源管理器

    前两天升级系统,使用命令pacman -Syyu,大概是使用的是testing缘故,今天发现dolphin无法打开了,使用命令行打开,提示ldmp.so有问题. 解决方法如下: 一,使用命令:pacm ...

  4. 转载——Java与WCF交互(二):WCF客户端调用Java Web Service

    在上篇< Java与WCF交互(一):Java客户端调用WCF服务>中,我介绍了自己如何使用axis2生成java客户端的悲惨经历.有同学问起使用什么协议,经初步验证,发现只有wsHttp ...

  5. UITextView只能显示两行问题

    需求:UITextView只能显示两行 UITextView * textView = [[UITextView alloc]init]; textView.frame = CGRectMake(20 ...

  6. 洛谷 P2863 [USACO06JAN]牛的舞会The Cow Prom-强连通分量(Tarjan)

    本来分好组之后,就确定好了每个人要学什么,我去学数据结构啊. 因为前一段时间遇到一道题是用Lca写的,不会,就去学. 然后发现Lca分为在线算法和离线算法,在线算法有含RMQ的ST算法,前面的博客也写 ...

  7. python-urllib/urllib2模块

    urllib与urllib2: urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL.这意味着,你不可以伪装你的User Agent字符串等. ...

  8. 长安大学第四届“迎新杯”程序设计竞赛 F 打铁的箱子【数学/进制思维/折半枚举】

    题目描述 作为彩虹岛上最擅长打铁的人,

  9. java文件下载导出

    前台代码: $("#btnExport").click(function(){ top.$.jBox.confirm("确认要导出房屋信息吗?","系 ...

  10. [置顶] 一个简单好用的zabbix告警信息发送工具

    之前使用邮件和短信发送zabbix告警信息,但告警信息无法实时查看或者无法发送,故障无法及时通知运维人员. 后来使用第三方微信接口发送信息,愉快地用了一年多,突然收费了. zabbix告警一直是我的痛 ...