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

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

2:显示当前在线用户。

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

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

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

前端代码例如以下:

<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #fc5bff; padding: 2px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
form button { width: 9%; background: rgb(217, 222, 221); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<body>
<ul id="messages"></ul>
<ul><li id='typingshow'></li></ul>
<div id='joinshow'></div>
<div id='leftshow'></div>
<div id='onlineshow'></div>
<form action=""> <input id="m" autocomplete="off" /><button id='btn'>Send</button>
</form>
<script src="jquery-1.10.2.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var typingIps={};
var typing=false;
var lastTypingTime;
function updateTyping() {
if (!typing) {
typing = true;
socket.emit('typing');
}
lastTypingTime = (new Date()).getTime(); setTimeout(function () {
var typingTimer = (new Date()).getTime();
var timeDiff = typingTimer - lastTypingTime;
if (timeDiff >= 400 && typing) {
socket.emit('stop typing');
typing = false;
}
}, 400);
}
$('form').submit(function(){
socket.emit('chat message',$('#m').val());
socket.emit('stop typing');
typing = false;
$('#m').val('');
return false;
});
$('#m').keyup(function(){
updateTyping();
});
socket.on('online num',function(msg){
$('#onlineshow').text('当前在线'+msg+'人');
}); socket.on('join', function (msg) {
$('#joinshow').text(msg.ip+'增加');
});
socket.on('typing',function(msg){
typingIps[msg.ip]=msg.ip;
var typingArr=[];
for(var ip in typingIps){
typingArr.push(typingIps[ip]);
}
$('#typingshow').text(typingArr.join(',') + '正在输入...');
});
socket.on('stop typing',function(msg){
delete typingIps[msg.ip];
var typingArr=[];
for(var ip in typingIps){
typingArr.push(typingIps[ip]);
}
if(typingArr.length===0){
$('#typingshow').text('');
}else{
$('#typingshow').text(typingArr.join(',') + '正在输入...');
}
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg.ip+'说:'+msg.content));
});
socket.on('user left', function(msg){
$('#leftshow').text(msg.ip+'离开了');
$('#onlineshow').text('当前在线'+msg.onlineNum+'人');
});
</script>
</body>
</html>

服务端代码:

/**
* Created by luzhen on 14-11-10.
*/
var express = require('express');
var app=express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var ips={};
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
var onlineNum=0;
io.on('connection', function (socket) {
console.log(socket.request.connection.remoteAddress);
ips[socket.request.connection.remoteAddress]=socket.request.connection.remoteAddress;//clientip
//socket.handshake.address 服务端ip
onlineNum++;
socket.broadcast.emit('join', {'ip':socket.request.connection.remoteAddress});//广播新用户增加 io.emit('online num',onlineNum);//广播当前在线人数 socket.on('chat message', function (msg) {
io.emit('chat message', {ip:socket.request.connection.remoteAddress,'content':msg});
console.log('message: ' + msg);
}); socket.on('typing', function (msg) {
socket.broadcast.emit('typing', {'ip':socket.request.connection.remoteAddress});
});
socket.on('stop typing', function (msg) {
socket.broadcast.emit('stop typing', {'ip':socket.request.connection.remoteAddress});
}); socket.on('disconnect',function(){
delete ips[socket.request.connection.remoteAddress];
onlineNum--;
socket.broadcast.emit('user left', {'ip':socket.request.connection.remoteAddress,'onlineNum':onlineNum});
});
}); http.listen(3000, function () {
console.log('listening on *:3000');
});

新增了防止刷屏功能,完整代码开源在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. 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---56

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

  2. 用C#将XML转换成JSON

    本文旨在介绍如果通过C#将获取到的XML文档转换成对应的JSON格式字符串,然后将其输出到页面前端,以供JavaScript代码解析使用.或许你可以直接利用JavaScript代码通过Ajax的方式来 ...

  3. PHP二维数组排序研究

    前几天在项目中碰到了一个问题,在做商城的时候,要对一个店铺里所有商品进行价格排序,而且每一种商品都拥有多个规格,要取到所有商品中所有规格的最低价和最高价,发现PHP有很友好的函数帮助我们进行筛选. 使 ...

  4. 交换机的MAC地址作用

    交换机的MAC地址在交换机进行数据交换时是没有作用的,因为交换机并不对转发的数据帧进行拆包重封装. 如果只是完成数据帧交换,则可以不要MAC地址(仅指二层交换机,三层交换机完成路由功能自然每个端口得有 ...

  5. HDU 5135.Little Zu Chongzhi's Triangles-字符串 (2014ACM/ICPC亚洲区广州站-重现赛)

    Little Zu Chongzhi's Triangles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 ...

  6. Codeforces 631B Print Check (思维)

    题目链接 Print Check 注意到行数加列数最大值只有几千,那么有效的操作数只有几千,那么把这些有效的操作求出来依次模拟就可以了. #include <bits/stdc++.h> ...

  7. 洛谷——P1977 出租车拼车

    题目背景 话说小 x 有一次去参加比赛,虽然学校离比赛地点不太远,但小 x 还是想坐 出租车去.大学城的出租车总是比较另类,有“拼车”一说,也就是说,你一个人 坐车去,还是一堆人一起,总共需要支付的钱 ...

  8. noip2017集训测试赛(三)Problem C: MST

    题面 Description 给定一个n个点m条边的连通图,保证没有自环和重边.对于每条边求出,在其他边权值不变的情况下,它能取的最大权值,使得这条边在连通图的所有最小生成树上.假如最大权值为无限大, ...

  9. Ubuntu 16.04下IntelliJ IDEA菜单显示乱码的问题解决

    说明:这个问题一般是Ubuntu安装时默认使用了中文,而IDEA默认是以系统默认字体为主,所以就会出现乱码:要解决这种问题,就是在IDEA启动时强制设置为英文. 解决方式: 在idea.vmoptio ...

  10. COFF - 中间文件格式解析

    http://www.cnblogs.com/weikanzong/p/5296739.html