Node.js 为实现tcp 提供了一个模块->net 使用时直接require这个模块前端
let net = require('net');
let server = net.createServer(function(socket){
server.maxConnections = 2;
server.getConnections(function(err,count){
socket.write(`当前最大容纳${server.maxConnections},如今${count}人`)
});
socket.setEncoding('utf8');
socket.on('data',function(data){
console.log(data);
socket.end();
server.close();
server.unref();
});
socket.on('end',function(){
console.log('客户端关闭');
});
});
let port = 8080;
server.listen(port,'localhost',function(){
console.log(`server start ${port}`)
});
// close事件只有调用close方法才会触发
server.on('close',function(){
console.log('服务端关闭');
})
//当端口被占用了,更改端口号
server.on('error',function(err){
//EADDRINUSE 当前端口号被调用
if(err.code === 'EADDRINUSE'){
server.listen(++port)
}
});
复制代码
能够经过telnet localhost 8080 (telnet会有乱码问题,不太好用)
或用putty工具来访问服务,个人设置以下,打开一个与服务器的链接后,回车即发送内容到服务node
let net = require('net');
let path = require('path');
let ws = require('fs').createWriteStream(path.join(__dirname,'./1.txt'));
// pipe (readale data不能同时使用)
let server = net.createServer(function(socket){
socket.pipe(ws,{end:false});
setTimeout(function(){
ws.end(); // 关闭可写流
socket.unpipe(ws); // 取消管道
},5000)
});
server.listen(8080);
复制代码
利用可读流pipe方法,边读取客户端输入的内容,边写入文件,可是当多个客户端输入内容时,若是一个客户端关闭,当前链接的socket就会关闭,同时会关闭ws可写流,但多个socket用的一个ws,因此参数{end:false} 用于设置这个可写流不关闭,其余未关闭的客户端仍然可写缓存
let net = require('net');
let server = net.createServer(function(socket){
socket.pause();
socket.setTimeout(5000);
socket.on('data',function(chunk){
socket.pause();
console.log(chunk);
})
socket.on('timeout',function(){
//socket.resume();
socket.end();
});
});
server.listen(8080);
复制代码
客户端访问服务端时,服务将一个文件发送给客户端bash
先建立一个文件服务器
let fs = require('fs');
fs.writeFileSync(__dirname+'/1.txt',Buffer.alloc(1024*1024*10));
复制代码
let net = require('net');
let rs = require('fs').createReadStream(__dirname+'/1.txt');
let server = net.createServer(function(socket){
rs.on('data',function(chunk){
let flag = socket.write(chunk);
console.log(flag);
console.log('缓存区的大小'+socket.bufferSize);
});
//可写流的缓存区的数据所有写到目标文件时触发
socket.on('drain',function(){
console.log('清空缓存')
})
});
server.listen(8080);
复制代码
socket.bufferSize : 缓存区的大小socket
socket.destroy();//销毁sockettcp
let net = require('net');
let clients = {}; //保存{用户名:socket}的映射
// 发言 将聊天内容发送给其余几我的
function broadcast(nickname,chunk){
Object.keys(clients).forEach(key=>{
//本身聊天的内容,不该该发送给本身
if(key!=nickname){
clients[key].write(`${nickname}:${chunk} \r\n`);
}
})
}
let server = net.createServer(function(socket){
server.maxConnections = 3; //容许同时3我的聊天
// 当客户端链接服务端时,提示用户输入用户名
server.getConnections((err,count)=>{
socket.write(`欢迎来到聊天室 当前用户数${count}个,请输入用户名\r\n`);
});
let nickname;
socket.setEncoding('utf8');
//当一个用户关闭了聊天,销毁socket,并删除用户
socket.on('end',function(){
clients[nickname] &&clients[nickname].destroy();
delete clients[nickname]; // 删除用户
});
socket.on('data',function(chunk){
chunk = chunk.replace(/\r\n/,'')
//若是nickname存在,说明用户输入的是聊天内容
if(nickname){
// 发言,将聊天内容发送给其余几我的
broadcast(nickname,chunk);
}else{
//若是不存在nickname时,用户输入的内容就是nickname
nickname = chunk;
clients[nickname] = socket;
socket.write(`您的新用户名是${nickname} \r\n`);
}
});
});
server.listen(8080);
复制代码
该聊天室的功能以下:
一、默认状况下用户名是匿名
二、经过关键命令更名, r:用户名
三、支持显示在线的用户列表 l
四、广播的功能,将聊天内容发送给全部其余在线用户 b:xxx
五、私聊的功能,只发送内容给指定用户 s:用户名:聊天内容
函数
let net = require('net');
let clients = {};
// 更名 r命令
function rename(key,data,socket){
clients[key].nickname = data;
socket.write(`您当前的用户名是${data}\r\n`);
}
// 展现用户列表 l命令
function list(socket){
let str = `当前用户列表是:\r\n`
let ls = Object.keys(clients).map(key=>{
return clients[key].nickname;
}).join('\r\n');
socket.write(str+ls+'\r\n');
}
// 私聊 nickname:用户名 content:发送的内容 key
function private(nickname,content,key){
let user;
Object.keys(clients).forEach(function(key){
if(clients[key].nickname === nickname){
user = clients[key].socket;
}
});
user.write(clients[key].nickname+":"+content+'\r\n');
}
//广播
function broadcast(nickname,content){
Object.keys(clients).forEach(item=>{
if(clients[item].nickname!= nickname){
clients[item].socket.write(content+'\r\n')
}
})
}
let server = net.createServer(function (socket) {
//用户默认是匿名的,因此用socket.remoteAddress + socket.remotePort来标识一个用户
let key = socket.remoteAddress + socket.remotePort; // 惟一
clients[key] = {nickname:'匿名',socket}//默认用户名
server.getConnections((err, count) => {
socket.write(`欢迎来到聊天室 当前用户${count}个\r\n`);
});
socket.setEncoding('utf8');
socket.on('data', function (chunk) {
chunk = chunk.replace(/\r\n/, '');
let chars = chunk.split(':');
switch (chars[0]) {
case 'r': // r:zhangsan
rename(key,chars[1],socket);
break;
case 'l':
list(socket);
break;
case 'b': // b:content
broadcast(key,chars[1]);
break;
case 's': // s:用户名:content
private(chars[1],chars[2],key);
break;
default:
socket.write('当前命令没法解析,从新输入\r\n')
}
});
});
server.listen(8080, function () {
console.log(`server start 8080`);
})
复制代码
let net = require('net');
let socket = net.createConnection({port:8080},function(){
socket.write('hello');
socket.on('data',function(data){
console.log(data);
});
});
复制代码
服务端测试代码工具
let net = require('net');
let server = net.createServer(function(socket){
socket.setEncoding('utf8');
socket.on('data',function(data){
console.log(data);
});
});
server.on('connection',function(){
console.log('客户端链接')
})
server.listen(8080);
复制代码
启动服务器,node命令执行客户端文件便可看到效果测试
客户端(不须要绑定端口,随机分配)
let dgram = require('dgram');
//建立socket
let socket = dgram.createSocket('udp4');
//发送消息
socket.send('hello',8080,function(){
console.log('成功')
});
//接收消息
socket.on('message',function(data){
console.log(data.toString());
})
复制代码
服务端
let dgram = require('dgram');
let socket = dgram.createSocket('udp4');
// 服务端监听一个端口 数据到来时 能够读出信息
socket.bind(8080,'localhost',function(){
//读取消息
socket.on('message',function(data,rinfo){
console.log(data.toString());
//发送消息
socket.send('hello',rinfo.port);
})
});
复制代码