nodejs 服务器实现区分多客户端请求服务
初始实现
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 服务器实现区分多客户端请求服务的更多相关文章
- MySQL服务器是怎么处理客户端请求的
不论MySQL客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果).那服务器进 ...
- 客户端请求服务器端通信, Web 编程发展基础|乐字节
乐字节的小伙伴们,好久不见,甚是想念啊! 前面我发布的文章算是把Java初级基础阶段讲完了,接下来小乐将会给大家接着讲Java中级阶段——Javaweb. 首先,我们要看看Javaweb阶段主要重点掌 ...
- JSP基础知识➣客户端请求与服务端响应(三)
JSP客户端请求 浏览器请求服务器端,信息头的一些重要内容,在以后的网络编程中将会经常见到这些信息: Accept:指定浏览器或其他客户端可以处理的MIME类型.它的值通常为 image/png 或 ...
- 自己封装的Socket组件,实现服务端多进程共享Socket对象,协同处理客户端请求
DotNet.Net.MySocket是SLB.NET(Server Load Balance服务器负载均衡)项目中的核心组件. 在实际的项目中发现,单进程的服务端处理高并发的客户请求能力有限. 所以 ...
- ICE学习第四步-----客户端请求服务器返回数据
这次我们来做一个例子,流程很简单:客户端向服务器发送一条指令,服务端接收到这条指令之后,向客户端发送数据库中查询到的数据,最终显示在DataGridView上. 根据上一篇文章介绍的Slice语法,我 ...
- ajax客户端请求与服务端响应浅谈
AJAX,即Asynchronous Javascript And XML,AJAX本质是在HTTP协议的基础上以异步的方式与服务器进行通信. 所谓的异步,是指某段程序执行不会阻塞其他程序执行,其表现 ...
- http客户端请求及服务端详解
http客户端请求及服务端详解 引言 HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展. ...
- javaWeb项目中的路径格式 请求url地址 客户端路径 服务端路径 url-pattern 路径 获取资源路径 地址 url
javaweb项目中有很多场景的路径客户端的POST/GET请求,服务器的请求转发,资源获取需要设置路径等这些路径表达的含义都有不同,所以想要更好的书写规范有用的路径代码 需要对路径有一个清晰地认知 ...
- 服务端如何获取客户端请求IP地址
服务端获取客户端请求IP地址,常见的包括:x-forwarded-for.client-ip等请求头,以及remote_addr参数. 一.remote_addr.x-forwarded-for.cl ...
随机推荐
- virtualbox+vagrant学习-3-Vagrant Share-3-SSH Sharing
SSH Sharing vagrant share通过向vagrant share提供--SSH标志,使远程SSH访问vagrant环境变得非常容易. 如果你想让同事访问你的SSH,以便对ops问题进 ...
- zabbix 监控机器监听的端口 + 触发器 表达式理解
在zabbix web 页面配置item,监控监听的21端口 配置trigger 参考:http://www.cnblogs.com/saneri/p/6126786.html 5. {www.zab ...
- [图解tensorflow源码] Graph 图模块 (UML视图)
- Python的 GUI 框架
Python的 GUI 框架 Tkinter Python内嵌的gui环境,使用TCL实现,python IDLE由Tkinter实现 历史悠久,perl中有对应的perlTk.Python标准安装包 ...
- iOS url出现特殊字符处理 -- stringByAddingPercentEncodingWithAllowedCharacters
stringByAddingPercentEscapesUsingEncoding(只对 `#%^{}[]|\"<> 加空格共14个字符编码,不包括”&?”等符号), i ...
- #leetcode刷题之路48-旋转图像
给定一个 n × n 的二维矩阵表示一个图像.将图像顺时针旋转 90 度.说明:你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要使用另一个矩阵来旋转图像.示例 1:给定 matrix ...
- MySQL日期时间处理函数
-- MySQL日期时间处理函数SELECT NOW() FROM DUAL;-- 当前日期时间:2017-05-12 11:41:47-- 在MySQL里也存在和Oracle里类似的dual虚拟表: ...
- MongoDB相关操作
1. 连接MongoDB <?php //1.连接到MongoDB $host = "127.0.0.1"; $port = 27017; $server = " ...
- SEO优化上首页之搜索引擎蜘蛛Spider原理
Spider,蜘蛛,又名网页网络爬虫.网络机器人,是按照一定策略不断抓取互联网网页的特定程序.蜘蛛抓回的页面创建索引后参与排名,等待用户检索.为了网站优化自然排名上首页,精灵儿工作室下面详细剖析Spi ...
- 洛咕 P4528 [CTSC2008]图腾
洛咕 P4528 [CTSC2008]图腾 神题orz. 先约定abcd表示\(1\leq A<B<C<D\leq n\),而且\(y_a,y_b,y_c,y_d\)的排名正好是\( ...