Node创建TCP聊天
//创建新的tcp服务器
var net = require('net');
var chatServer = net.createServer()
chatServer.on('connection',function(client){
client.write('Hi\n');
client.write('Bye\n');
client.end();
})
chatServer.listen(9000)
/*代码的第一行,我们加载了net模块。这个模块包含了Node需要的所有TCP功能。
接着我们调用net.createServer()方法来厂车间一个新的TCP服务器。有了这个
服务器我们需要他做点事。这里调用on()方法来添加一个事件监听器每当有新的客户端
通过网络连接接入服务器,就会触发connection事件,事件监听器就会调用我们指定的函数。
链接事件在调用回调函数是,会传给我们新的客户端对应的TCP scoket对象的引用。我们把
他引用命名为client。调用client.write(),就能发送信息给该客户端,然后调用client.end()
方法关闭连接。
*/
//监听所有的链接请求
var net = require('net');
var chatServer = net.createServer()
chatServer.on('connection',function(client){
client.write('Hi\n');
client.on('data',function(data){
console.log(data)
})
})
chatServer.listen(9000)
/*这里添加了另外一个事件监听器,调用的是client.on()。注意我们是在connection回调函数作用域
中添加事件监听器,这样就能访问到链接事件所对应的client对象。新监视器关注的是data事件,每当
client发送数据给服务器时,这一事件都会触发*/
//客户端之间的通信
var net = require('net')
var chatServer = net.createServer(),
clientList = []
chatServer.on('connection',function(client){
client.write('Hi!\n');
clientList.push(client)
client.on('data',function(data){
for (var i = 0; i < clientList.length; i+=1) {
//把数据发送给客户端
clientList[i].write(data)
}
})
})
chatServer.listen(9000)
/*服务器没有接收记录他收到的任何消息,而且把列表中的每个客户端都轮询一遍,
并把消息转发出去,发送消息的时候,没有检查发送者是谁,只是简单的把消息转发
给所有的客户端*/
//改进消息发送
var net = require('net')
var chatServer =net.createServer(),
clientList = []
chatServer.on('connection',function(client){
client.name = client.remoteAddress + ':' + client.remotePort
client.write('Hi ' + client.name + '\n');
clientList.push(client)
client.on('data',function(data){
broadcase(data,client)
})
})
function broadcase(message,client){
for(var i = 0;i < clientList.length;i += 1){
if(client !== clientList[i]){
clientList[i].write(client.name + "says: " + message + '\n')
}
}
}
chatServer.listen(9000)
/*在connection事件监听器上为每个client对象上增加name属性
为什么我们能为client对象添加属性
因为闭包绑定了每个client对象和相应的请求。于是,在闭包内疚可以利用
client.remoteAddress和client.remotePort来创建client和name属性
client.remoteAddress是客户端所在的IP地址
client,remotePort是客户端接收从服务器返回数据的TCP端口
当不同的客户端从一个IP发起连接时,他们各自会有唯一的remotePort。
以后再向client发送消息时,我们就能唯一标识来找到他
我们还把处理data的事件监听器放到了broadcast函数中,这样,通过
调用broadcast函数就可以把消息发送到所有客户端。这一次,把发起消息
data的client对象传递进去,以便把他从接收消息的客户端列表中排除掉。
我们还把client.name加到要发送的消息上,好让其他客户端清楚消息来源*/
/*此种通信弊端:建立3个tcp通信,当断掉其中一个,在向其发送消息,即
调用broadcast()的时候,服务器会往一个断开的客户端写入数据,因为他所对应
的socket已经无法写入和读取了,而对socket进行write()操作时,Node程序会抛出
异常,这将导致其他服务器掉线
这个问题应该从两个方面来解决,首先保证在一个客户端断开的时候,要把他从客户端
列表中移除,防止他在调用write方法。V8引擎也会把相应的scoket对象作为垃圾回收
并释放内存。其次,更保险的方式不调用write方法*/
//把聊天服务器改造的更加健壮
var net = require('net')
var chatServer =net.createServer(),
clientList = []
chatServer.on('connection',function(client){
client.name = client.remoteAddress + ':' + client.remotePort
client.write('Hi ' + client.name + '\n');
clientList.push(client)
client.on('data',function(data){
broadcase(data,client)
})
client.on('end',function(){
clientList.splice(clientList.indexOf(client),1)
})
})
function broadcase(message,client){
for(var i = 0;i < clientList.length;i += 1){
if(client !== clientList[i]){
clientList[i].write(client.name + "says: " + message + '\n')
}
}
}
chatServer.listen(9000)
/*先处理断开的客户端。当一个客户端断开时,要把它从客户端列表移除。这时
可以用end事件来完成。一个socket断开连接会触发end事件,表示他要关闭。
此时,调用Array.splice()将客户端从cliectList列表移除。Array.indexOf()
方法用于找到客户端在列表的位置,然后splice()把他从列表移除。之后,
下一个客户端调用broadcast方法时,已经断开的客户端将不出现在列表中*/
//检查socke的可写状态
var net = require('net')
var chatServer =net.createServer(),
clientList = []
chatServer.on('connection',function(client){
client.name = client.remoteAddress + ':' + client.remotePort
client.write('Hi ' + client.name + '\n');
clientList.push(client)
client.on('data',function(data){
broadcase(data,client)
})
})
function broadcase(message,client){
var cleanup = []
for(var i = 0;i < clientList.length;i += 1){
if(client !== clientList[i]){
if(clientList[i].writable){
clientList[i].write(client.name + "says: " + message + '\n')
} else{
cleanup.push(clientList[i])
clientList[i].destroy()
}
}
}
//在写如入循环中删除死节点,消除垃圾索引
for(i = 0;i < cleanup.length;i += 1){
clientList.splice(clientList.indexOf(cleanup[i]),1)
}
}
chatServer.listen(9000)
/*调用broadcast函数的时候,检查一下socket是否可写,以确保不会因为任何一个不可写
的socket导致异常。不仅如此,发现任何不可写的socket后,还要通过Socket.destroy()
方法将其关闭并从clientList中移除。注意,遍历clientList的过程没有移除socket,*/
Node创建TCP聊天的更多相关文章
- 基于node的tcp客户端和服务端的简单通信
1.简单介绍下TCP/IP TCP/IP是互联网相关协议的集合,分为以下四层:应用层.传输层.网络层.数据链路层. 分成四层的好处是,假如只有一层,某个地方需要改变设计时,就必须把所有整体替换掉,而分 ...
- 用C#基于WCF创建TCP的Service供Client端调用
本文将详细讲解用C#基于WCF创建TCP的Service供Client端调用的详细过程 1):首先创建一个Windows Service的工程 2):生成的代码工程结构如下所示 3):我们将Servi ...
- 《转》 Openstack Grizzly 指定 compute node 创建 instance
声明:此文档仅仅做学习交流使用,请勿用作其它商业用途 作者:朝阳_tony 邮箱:linzhaolover@gmail.com 2013年6月4日9:37:44 星期二 转载请注明出处:http:// ...
- 使用nodejs的net模块创建TCP服务器
使用nodejs的net模块创建TCP服务器 laiqun@msn.cn Contents 1. 代码实现 2. 使用telnet连接服务器测试 3. 创建一个TCP的client 1. 代码实现 ; ...
- 026.3 网络编程 TCP聊天
分为客户端和服务端,分别进行收发操作##########################################################################客户端:###思 ...
- swoole 创建tcp服务器
server.php <?php /** * 创建tcp服务器 * Date: 2019/1/15 */ $serv = new swoole_server('127.0.0.1', 9501) ...
- node创建一个简单的web服务
本文将如何用node创建一个简单的web服务,过程也很简单呢~ 开始之前要先安装node.js 1.创建一个最简单的服务 // server.js const http = require('http ...
- 【Swoole】简单安装与创建TCP服务器
pecl install swoole PHP的异步.并行.高性能网络通信引擎,使用纯C语言编写,提供了php语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据 ...
- 170925_1 Python socket 创建TCP的服务器端和客户端
[Python版本]3.6 [遇到的问题] 客户端和服务器端都遇到:TypeError: a bytes-like object is required, not 'str' [解决方案] 参考:ht ...
随机推荐
- Python3操作MySQL,查询数据并保存到文件中
我们在测试过程中,可能需要到数据库中拉去一些数据,为从测试准备.比如最近在做接口性能测试的时候,就需要很多数据来支撑,所以就需要的数据库去查询数据,下面就是python3 查询 mysql 并且保存到 ...
- Linux内核分析课程笔记(一)
linux内核分析课程笔记(一) 冯诺依曼体系结构 冯诺依曼体系结构实际上就是存储程序计算机. 从两个层面来讲: 从硬件的角度来看,冯诺依曼体系结构逻辑上可以抽象成CPU和内存,通过总线相连.CPU上 ...
- Sprint 3计划
一.计划目标: 1.完成基本的首页面的信息查询功能 2.学生家教用户注册和登录,将信息存储到数据库 3.完成家教的资格评定设定和个人教学内容备份信息 二.燃尽图 三.项目具体工作细则 待明天工作会议分 ...
- Cookie 和 Session 的区别
[[ from 老生常谈session,cookie的区别,安全性 ]] 一,为什么session,cookie经常会有人提到 做web开发的人基本上都会用session和cookie,但是仅仅只是会 ...
- 快捷获取浏览器(navigator对象)的全部属性
理论: navigator对象包含关于web浏览器的信息,浏览器的类型,版本信息都可以从该对象获取. 属性 说明 appCodeName 浏览器代码说明 appName 浏览器名称 appVe ...
- WPF 中获取DataGrid 模板列中控件的对像
WPF 中获取DataGrid 模板列中控件的对像 #region 当前选定行的TextBox获得焦点 /// <summary> /// 当前选定行的TextBox获得焦点 /// &l ...
- 重新想象 Windows 8 Store Apps (70) - 其它: 文件压缩和解压缩, 与 Windows 商店相关的操作, app 与 web, 几个 Core 的应用, 页面的生命周期和程序的生命周期
[源码下载] 重新想象 Windows 8 Store Apps (70) - 其它: 文件压缩和解压缩, 与 Windows 商店相关的操作, app 与 web, 几个 Core 的应用, 页面的 ...
- 精进不休 .NET 4.5 (12) - ADO.NET Entity Framework 6.0 新特性, WCF Data Services 5.6 新特性
[索引页][源码下载] 精进不休 .NET 4.5 (12) - ADO.NET Entity Framework 6.0 新特性, WCF Data Services 5.6 新特性 作者:weba ...
- 开源的javascript实现页面打印功能,兼容所有的浏览器(情况属实)
这篇文章完全是属于技术文章,也是记录一下自己在项目当中遇到的坑爹问题啊,因为是B/S的程序,所以打印功能还是必须要有的,对于打印我选择了一个js插件,发现非常的简单和方便,所以这里拿出来和大家分享一下 ...
- 【GPU编解码】GPU硬解码---CUVID
问题描述:项目中,需要对高清监控视频分析处理,经测试,其解码过程所占CPU资源较多,导致整个系统处理效率不高,解码成为系统的瓶颈. 解决思路: 利用GPU解码高清视频,降低解码所占用CPU资源,加速解 ...