样例地址http://www.lxrtalk.com/

我们实现的思路是,当有一个人发送过来消息,我们就广播给其他客户端。

var net = require('net');
var chatServer = net.createServer(),
clientList = [];//已连接的client列表
chatServer.on('connection', function(client) {
// name 的自定义属性,用于表示哪个客户端(客户端的地址+端口为依据)
client.name = client.remoteAddress + ':' + client.remotePort;
client.write('Hi ' + client.name + '!\n');
  //加入在线列表
clientList.push(client);
client.on('data', function(data) {
broadcast(buffer, client);// 发送给其他客户端
});
client.on('end', function() {
//从在线列表中移除
clientList.splice(clientList.indexOf(client), 1);
});
});
chatServer.listen(9000);

这里broadcast方法发送给其他客户端,代码如下

function broadcast(message, client) {
for(var i=0;i<clientList.length;i+=1) {
//发送给其他人
if(client !== clientList[i]) {
var msg=client.name + " says: " + message;
console.log(msg);
clientList[i].write(msg);
}
}
}

但此时,我们会发现,每发送一个字符,其他客户端都会收到一条消息。

比如我们发送”abcd“,如果client.name为”192.168.1.2:5486“,其他用户收到的是:
192.168.1.2:5486 says: a
192.168.1.2:5486 says: b
192.168.1.2:5486 says: c
192.168.1.2:5486 says: d

此时,我们需要考虑分割符将我们要发送的完整的一句话分开,最终我采取的是回车换行分割。最终代码如下:

// 在前者的基础上,实现 Client --> Sever 的通讯,如此一来便是双向通讯
var net = require('net');
var chatServer = net.createServer(),
clientList = [];//已连接的client列表
var clientsBuffer={};
//telnet 127.0.0.1 9000
chatServer.on('connection', function(client) {
// name 的自定义属性,用于表示哪个客户端(客户端的地址+端口为依据)
client.name = client.remoteAddress + ':' + client.remotePort;
client.write('Hi ' + client.name + '!\n');
clientList.push(client);
clientsBuffer[client.name]=new Buffer(0);//发送消息的缓存
client.on('data', function(data) {
console.log(data);
var myBuffer=clientsBuffer[client.name];
console.log(myBuffer);
//以回车换行为分割
if(data.equals(new Buffer([0x0d,0x0a]))){
broadcast(myBuffer, client);// 接受来自客户端的信息
clientsBuffer[client.name]=new Buffer(0);//清空缓存
}else{
//将发送过来的字符拼入缓存中
var buflist=[myBuffer,data];
clientsBuffer[client.name]=Buffer.concat(buflist,myBuffer.length+data.length);
} });
client.on('end', function() {
clientList.splice(clientList.indexOf(client), 1); // 删除数组中的制定元素。这是 JS 基本功哦~
});
client.on('error', function(e) {
console.log(e);
});
});
/**
* 广播给其他所有用户
* @param message 消息内容
* @param client 发送人客户端
*/
function broadcast(message, client) {
var cleanup = [];//需要销毁的列表
for(var i=0;i<clientList.length;i+=1) {
if(client !== clientList[i]) {
if(clientList[i].writable) { // 先检查 sockets 是否可写
var msg=client.name + " says " + message;
console.log(msg);
clientList[i].write(msg);
} else {
cleanup.push(clientList[i]) // 如果不可写,收集起来销毁。销毁之前要 Socket.destroy() 用 API 的方法销毁。
clientList[i].destroy()
}
}
}
//销毁
for(i=0;i<cleanup.length;i+=1) {
clientList.splice(clientList.indexOf(cleanup[i]), 1)
}
}
chatServer.listen(9000);

nodejs初探(四)实现一个多人聊天室的更多相关文章

  1. 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室

    原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  2. 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室

    原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  3. 使用Go语言+Protobuf协议完成一个多人聊天室

    软件环境:Goland Github地址 一.目的 之前用纯逻辑垒完了一个可登入登出的在线多人聊天室(代码仓库地址),这次学习了Protobuf协议,于是想试着更新下聊天室的版本. 主要目的是为了掌握 ...

  4. Asp.net MVC + Signalr 实现多人聊天室

    Asp.net SignalR 简介: 首先简单介绍一下Signalr ,我也是刚接触,觉得挺好玩的,然后写了一个多人聊天室. Asp.net SignalR 是为Asp.net 开发人员提供的一个库 ...

  5. 利用Node.js的Net模块实现一个命令行多人聊天室

    1.net模块基本API 要使用Node.js的net模块实现一个命令行聊天室,就必须先了解NET模块的API使用.NET模块API分为两大类:Server和Socket类.工厂方法. Server类 ...

  6. Apache MiNa 实现多人聊天室

    Apache MiNa 实现多人聊天室 开发环境: System:Windows JavaSDK:1.6 IDE:eclipse.MyEclipse 6.6 开发依赖库: Jdk1.4+.mina-c ...

  7. C 基于UDP实现一个简易的聊天室

    引言 本文是围绕Linux udp api 构建一个简易的多人聊天室.重点看思路,帮助我们加深 对udp开发中一些api了解.相对而言udp socket开发相比tcp socket开发注意的细节要少 ...

  8. java socket之多人聊天室Demo

    一.功能介绍 该功能实现了一个类似QQ的最简单多人聊天室,如下图所示. 二.目录结构 三.服务端 1)SocketServer类,该类是服务端的主类,主要负责创建聊天窗口,创建监听客户端的线程: pa ...

  9. 玩转Node.js(四)-搭建简单的聊天室

    玩转Node.js(四)-搭建简单的聊天室 Nodejs好久没有跟进了,最近想用它搞一个聊天室,然后便偶遇了socket.io这个东东,说是可以用它来简单的实现实时双向的基于事件的通讯机制.我便看了一 ...

随机推荐

  1. jersey处理支付宝异步回调通知的问题:java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded; text/html; charset=UTF-8'

    tcpflow以流为单位分析请求内容,非常适合服务器端接口类服务查问题 这次遇到的问题跟支付宝支付后的回调post结果有关 淘宝的代码例子: public void doPost(HttpServle ...

  2. [计算机、网络相关历史]unix简史

    本文2001年由台湾“网络农夫”所写,其人生平不祥,此文受鸟哥大力推崇,两人应该相识.文章写得很不错,应该是查了很多资料整理而成的,美中不足的是好多语句不通顺,国考语文绝对不及格,哈哈. 0.我的准备 ...

  3. cookie窃取和session劫持

    Updates 2014-08-17 感谢@搞前端的crosser的提醒,加入了HTTP Response Splitting的内容. 此篇文章的Presentation戳这里. 一.cookie的基 ...

  4. 关于js中的setTimeout和setInterval

    http://ejohn.org/blog/how-javascript-timers-work 这是John的一篇博文说到setTimeout和setInterval的区别,在看js高效图形编程的时 ...

  5. 北大poj-1088

    滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 88484   Accepted: 33177 Description ...

  6. QT中给各控件增加背景图片(可缩放可旋转)的几种方法

    http://blog.csdn.net/liukang325/article/details/44832397 1. 给QPushButton 增加背景图片:背景图片可根据Button大小自由缩放. ...

  7. C语言之共用体

    最近在复习C语言,特再次记录: 有时需要将几种不同类型的变量存放到同一段内存单元中.如一个int.float.char放在同一个地址开始的内存单元中.,也就是使用覆盖技术,几个变量相互覆盖,称之为共用 ...

  8. Call to undefined function curl_init()

    运行PHP不支持curl_init()的解决方法: 1.修改php.ini,将;extension=php_curl.dll前面的分号去掉(同时检查扩展的引用路径是否正确)2.拷贝libeay32.d ...

  9. Magento文件系统目录结构

    magento │  .htaccess│  cron.php //系统cron程序,修改 linux的cron运行,加入magento的一些定时处理│  cron.sh│  favicon.ico ...

  10. VS 2010 编译 Openssl

    VS 2010 编译 Openssl 1. 编译环境: Visual Studio 2010 Windows 7 64 旗舰版 openssl-1.0.1s 2. 下载安装ActivePerl,下载下 ...