初始实现

var net = require('net');//1 引入net模块
var chatServer = net.createServer();//创建net服务器
var clientList=[];//保存多个客户端的数组
chatServer.on('connection', function (client) {//服务器连接客户端
client.name=client.remoteAddress+':'+client.remotePort;
/*增加name属性*/
client.write('Hi'+client.name+'!\n');
clientList.push(client);
client.on('data', function (data) {
/*添加事件监听器,这样就可以访问到连接事件所对应的client对象,当client发送数据给服务器时,这一事件就会触发*/
for(var i=0;i<clientList.length;i++){
if(clientList[i]!==this){
// 把数据发送给其他客户端
clientList[i].write(this.name+"says "+data);
}
}
});
});
chatServer.listen(9000, "127.0.0.1");//服务器端口

注意:这里有个坑——如果有个客户端断开连接,那么所有人都会玩完!
因为如果再往服务器发送消息,这时候服务器并不知道某个客户端已经断开了连接,因此会继续向其发送数据,但是这时断开的这个客户端对应的socket已经无法写入数据,而对已关闭的socket进行write()操作node程序会抛出异常,进而导致全军覆没。所以,这个问题应该从两个方面来解决:
(1)当客户端断开连接时,通知服务器,将其从客户端列表中移除,防止其调用write方法(V8引擎也会把响应的socket对象作为垃圾回收,并释放相应的内存);
(2)采用更保险的方式调用write()方法。
改进如下:

最后,监听客户端关闭事件,并记录错误

var net = require('net');//1 引入net模块
var chatServer = net.createServer();//创建net服务器
var clientList = [];//保存多个客户端的数组 chatServer.on('connection', function (client) {//服务器连接客户端
// console.log(' client remoteAddress =' + client.remoteAddress);
// console.log(' client remotePort = ' + client.remotePort);
client.name = client.remoteAddress + ':' + client.remotePort; /*增加name属性*/
client.write('Hi' + client.name + '!\n');
// console.log(''client.name+'connected');
clientList.push(client);
console.log('clientList length = ' + clientList.length);
for(var i = 0; i<clientList.length; i++){
console.log('client remoteAddress'+[i] + clientList[i].name);
}
client.on('data', function (data) {
/*添加事件监听器,这样就可以访问到连接事件所对应的client对象,当client发送数据给服务器时,这一事件就会触发*/
//广播消息给其他客户端
broadcast(data,client);
});
//监听客户端终止
client.on('end',function(){
console.log(''+client.name+'quit');//如果某个客户端断开连接,node控制台就会打印出来
clientList.splice(clientList.indexOf(client),1);
});
/*记录错误*/
client.on('error',function(e){
console.log(' error'+e);
}); function broadcast(message,client){
var cleanup=[];//断开了的客户端们
for (var i = 0; i < clientList.length; i++) {
if (clientList[i] !== client) {
//检查socket的可写状态
if (clientList[i].writable) {
// 把数据发送给其他客户端
clientList[i].write(client.name + "says " + message);
}else{
/*socket不可写,则将其从列表中移除*/
cleanup.push(clientList[i]);
clientList[i].destroy();
}
}
}
/*删除掉服务器的客户端数组中,已断开的客户端*/
for(var i=0;i<cleanup.length;i++){
clientList.splice(clientList.indexOf(cleanup[i]),1);
}
}
});
//服务器端口
chatServer.listen(9000, function(){
console.log("server bound : 9000");
});

nodejs 服务器实现区分多客户端请求服务的更多相关文章

  1. MySQL服务器是怎么处理客户端请求的

    不论MySQL客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果).那服务器进 ...

  2. 客户端请求服务器端通信, Web 编程发展基础|乐字节

    乐字节的小伙伴们,好久不见,甚是想念啊! 前面我发布的文章算是把Java初级基础阶段讲完了,接下来小乐将会给大家接着讲Java中级阶段——Javaweb. 首先,我们要看看Javaweb阶段主要重点掌 ...

  3. JSP基础知识➣客户端请求与服务端响应(三)

    JSP客户端请求 浏览器请求服务器端,信息头的一些重要内容,在以后的网络编程中将会经常见到这些信息: Accept:指定浏览器或其他客户端可以处理的MIME类型.它的值通常为 image/png 或 ...

  4. 自己封装的Socket组件,实现服务端多进程共享Socket对象,协同处理客户端请求

    DotNet.Net.MySocket是SLB.NET(Server Load Balance服务器负载均衡)项目中的核心组件. 在实际的项目中发现,单进程的服务端处理高并发的客户请求能力有限. 所以 ...

  5. ICE学习第四步-----客户端请求服务器返回数据

    这次我们来做一个例子,流程很简单:客户端向服务器发送一条指令,服务端接收到这条指令之后,向客户端发送数据库中查询到的数据,最终显示在DataGridView上. 根据上一篇文章介绍的Slice语法,我 ...

  6. ajax客户端请求与服务端响应浅谈

    AJAX,即Asynchronous Javascript And XML,AJAX本质是在HTTP协议的基础上以异步的方式与服务器进行通信. 所谓的异步,是指某段程序执行不会阻塞其他程序执行,其表现 ...

  7. http客户端请求及服务端详解

    http客户端请求及服务端详解 引言 HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展. ...

  8. javaWeb项目中的路径格式 请求url地址 客户端路径 服务端路径 url-pattern 路径 获取资源路径 地址 url

    javaweb项目中有很多场景的路径客户端的POST/GET请求,服务器的请求转发,资源获取需要设置路径等这些路径表达的含义都有不同,所以想要更好的书写规范有用的路径代码 需要对路径有一个清晰地认知 ...

  9. 服务端如何获取客户端请求IP地址

    服务端获取客户端请求IP地址,常见的包括:x-forwarded-for.client-ip等请求头,以及remote_addr参数. 一.remote_addr.x-forwarded-for.cl ...

随机推荐

  1. 关于EasyPoi导出Excel

    如果你觉得Easypoi不好用,喜欢用传统的poi,可以参考我的这篇博客:Springmvc导出Excel(maven) 当然了,万变不离其宗.Easypoi的底层原理还是poi.正如MyBatis ...

  2. 跳转到appstore下载app的链接 记录一下

    这是链接: https://itunes.apple.com/cn/app/da-dou-dou-lao-shi/id1395835036?mt=8 其中值得一提的是mt参数是啥意思 见下图:

  3. B. Our Tanya is Crying Out Loud

    http://codeforces.com/problemset/problem/940/B Right now she actually isn't. But she will be, if you ...

  4. Putty等工具中解决SSH连接超时断开的问题

    转自:http://www.putty.ws/putty-chaoshi 1 在 linux下的ssh命令:vim /etc/ssh/ssh_config 然后找到里面的ServerAliveInte ...

  5. 怎么用CIFilter给图片加上各种各样的滤镜_2

    上一篇讲了怎么找到能用的的滤镜和大概怎么去寻找... 这里接着说如何详细地给图片加滤镜效果..前的准备工作... . 1. 在找到想用的滤镜名字之后.须要知道这个滤镜究竟须要什么參数. . 例如以下图 ...

  6. 图片在线处理 webp!

    之前处理图片的方式是,小图标通过gulp配置的spritesmith雪碧图方式,.png会先用ps工具转成.jpg,然后jpg太大则用在线压缩工具来进行压缩(另外gulp系列的gulp-imagemi ...

  7. jquery animate() Alternate 语法

    前段时间在使用jQuery的animate() 函数时候用到Alternate方式.主要是要让数字自增到指定大小,且能看见数字增加过程. 一般使用如下方式: function autoPlusAnim ...

  8. LaTeX源代码显示宏包listings应用备忘之新语言定义

      我目前了解的LaTeX中有关源代码显示的宏包有两个,这里介绍其中的listings宏包.listings宏包中已经定义了部分计算机语言的显示样式,但还是有些语言没有定义,我们一起看一下如何定义新的 ...

  9. json keyname map

    var obj = { fname:'zhao', lname:'yao', parents:{ father:'zhao' }, children:[ { dname:'zhaoyiyi' } ] ...

  10. daily Tip

    daily tip :   <UserControl.Resources>         <Storyboard x:Name="sb1" x:Key=&quo ...