您好,登錄后才能下訂單哦!
1. TCP
在Node.js中,提供了net模塊用來實現(xiàn)TCP服務(wù)器和客戶端的通信。
1.1 TCP服務(wù)器
net.createServer([options][, connectionListener])
也可以通過監(jiān)聽connection事件的方式來指定監(jiān)聽函數(shù)
server.on('connection',function(socket){});
1.1.1 啟動TCP服務(wù)器
可以使用listen方法通知服務(wù)器開始監(jiān)聽客戶端的連接
server.listen(port,[host],[backlog],[callback])
server.on('listening',function(){});
1.1.2 使用TCP服務(wù)器
let net = require('net'); let server = net.createServer(function(socket){ console.log('客戶端已連接'); }); server.listen(8080,'localhost',function(){ console.log('服務(wù)器開始監(jiān)聽'); });
1.1.3 address
server.address()
1.1.4 getConnections
查看當前與TCP服務(wù)器建立連接的客戶端的連接數(shù)量以及設(shè)置最大連接數(shù)量
server.getConnections(callback); server.maxConnections = 2;
1.1.5 close
使用close方法可以顯式拒絕所有的客戶端的連接請求,當所有已連接的客戶端關(guān)閉后服務(wù)器會自動關(guān)閉,并觸發(fā)服務(wù)器的close事件。
server.close(); server.on('close',callback);
1.2 socket
1.2.1 address
net.Socket代表一個socket端口對象,它是一個可讀可寫流。
let net = require('net'); let util = require('util'); let server = net.createServer(function(socket){ server.getConnections((err,count)=>{ server.maxConnections = 1; console.log('最大連接數(shù)量%d,當前連接數(shù)量%d',server.maxConnections,count); }); let address = socket.address(); console.log('客戶端地址 %s',util.inspect(address)); });
1.2.2 讀取數(shù)據(jù)
let server = net.createServer(function (socket) { socket.setEncoding('utf8'); socket.on('data', function (data) { console.log('本次收到的內(nèi)容為%s,累計收到的字節(jié)數(shù)是%d', data, socket.bytesRead); }); });
1.2.3 監(jiān)聽關(guān)閉事件
let server = net.createServer(function (socket) { socket.on('end', function () { console.log('客戶端已經(jīng)關(guān)閉'); }); });
1.2.4 pipe
pipe方法可以將客戶端發(fā)送的數(shù)據(jù)寫到文件或其它目標中。
socket.pipe(destinatin,[options]);
options.end 設(shè)置為false時當客戶端結(jié)束寫操作或關(guān)閉后并不會關(guān)閉目標對象,還可以繼續(xù)寫入數(shù)據(jù)
let net = require('net'); let path = require('path'); let ws = require('fs').createWriteStream(path.resolve(__dirname, 'msg.txt')); let server = net.createServer(function (socket) { socket.on('data', function (data) { console.log(data); }); socket.pipe(ws, { end: false }); socket.on('end', function () { ws.end('over', function () { socket.unpipe(ws); }); }); });
1.2.5 unpipe
const net = require('net'); const path = require('path'); let file = require('fs').createWriteStream(path.join(__dirname, 'msg.txt')); let server = net.createServer(function (socket) { socket.pipe(file, { end: false }); setTimeout(function () { file.end('bye bye'); socket.unpipe(file); }, 5000); // socket.on('end', function () { // file.end('bye bye'); // }); }); server.listen(8080);
1.2.5 pause&resume
pause 可以暫停 data 事件觸發(fā),服務(wù)器會把客戶端發(fā)送的數(shù)據(jù)暫存在緩存區(qū)里
const net = require('net'); const net = require('net'); const path = require('path'); let file = require('fs').createWriteStream(path.join(__dirname, 'msg.txt')); let server = net.createServer(function (socket) { socket.pause(); setTimeout(function () { socket.resume(); socket.pipe(file); }, 10 * 1000); }); server.listen(8080);
1.2.6 setTimeout
let net = require('net'); let path = require('path'); let ws = require('fs').createWriteStream(path.resolve(__dirname, 'msg.txt')); let server = net.createServer(function (socket) { socket.setTimeout(5 * 1000); socket.pause(); socket.on('timeout', function () { socket.pipe(ws); }); //socket.setTimeout(0);取消超時時間的設(shè)置 }); server.listen(8080);
1.2 TCP客戶端
1.2.1 創(chuàng)建TCP客戶端
let socket = new net.Socket([options])
socket.connect(port, host, callback); socket.on('connect', callback);
1.2.2 向服務(wù)器端寫入數(shù)據(jù)、end 、error、destroy,close
socket.write(data,[encoding],[callback]);
let net = require('net'); let server = net.createServer(function (socket) { console.log("客戶端已經(jīng)連接"); socket.setEncoding('utf8'); socket.on('data', function (data) { console.log("已接收客戶端發(fā)送的數(shù)據(jù):%s", data); socket.write('服務(wù)器:' + data); }) socket.on('error', function (err) { console.log('與客戶端通信過程中發(fā)生了錯誤,錯誤編碼為%s', err.code); socket.destroy(); }); socket.on('end', function (err) { console.log('客戶端已經(jīng)關(guān)閉連接'); socket.destroy(); }); socket.on('close', function (hasError) { console.log(hasError ? '異常關(guān)閉' : '正常關(guān)閉'); }); }); server.listen(808, function () { let client = new net.Socket(); client.setEncoding('utf8'); client.connect(808, '127.0.0.1', function () { console.log('客戶端已連接'); client.write('hello'); setTimeout(function () { client.end('byebye'); }, 5000); }); client.on('data', function (data) { console.log('已經(jīng)接收到客戶端發(fā)過來的數(shù)據(jù):%s', data); }); client.on('error', function (err) { console.log('與服務(wù)器通信過程中發(fā)生了錯誤,錯誤編碼為%s', err.code); client.destroy(); }); });
1.2.3 close
停止server接受建立新的connections并保持已經(jīng)存在的connections
server.getConnections((err, count) => { if (count == 2) server.close(); });
1.2.4 unref&ref
unref方法指定發(fā)客戶端連接被全部關(guān)閉時退出應(yīng)用程序 如果將allowHalfOpen方法,必須使用與客戶端連接的socket端口對象的end 方法主動關(guān)閉服務(wù)器端連接
let net = require('net'); let server = net.createServer({ allowHalfOpen: true }, function (socket) { console.log("客戶端已經(jīng)連接"); socket.setEncoding('utf8'); socket.on('data', function (data) { console.log("已接收客戶端發(fā)送的數(shù)據(jù):%s", data); socket.write('服務(wù)器確認數(shù)據(jù):' + data); }) socket.on('error', function (err) { console.log('與客戶端通信過程中發(fā)生了錯誤,錯誤編碼為%s', err.code); socket.destroy(); }); socket.on('end', function (err) { console.log('客戶端已經(jīng)關(guān)閉連接'); socket.end(); server.unref(); }); socket.on('close', function (hasError) { if (hasError) { console.log('由于錯誤導(dǎo)致socket關(guān)閉'); server.unref(); } else { console.log('端口正常關(guān)閉'); } }); server.getConnections((err, count) => { if (count == 2) server.close(); }); }); server.listen(808, function () { }); server.on('close', function () { console.log('服務(wù)器關(guān)閉'); });
1.2.5 bufferSize
write的返回值和bufferSize屬性值
let server = net.createServer({ allowHalfOpen: true }, function (socket) { console.log("客戶端已經(jīng)連接"); socket.setEncoding('utf8'); let rs = fs.createReadStream(path.resolve(__dirname, 'a.txt'), { highWaterMark: 2 }); rs.on('data', function (data) { let flag = socket.write(data); console.log("flag:", flag); console.log('緩存字節(jié):' + socket.bufferSize); console.log('已發(fā)送字節(jié):' + socket.bytesWritten); }) socket.on('data', function (data) { console.log('data', data); }); socket.on('drain', function (err) { "緩存區(qū)已全部發(fā)送" }); });
1.2.6 keepAlive
當服務(wù)器和客戶端建立連接后,當一方主機突然斷電、重啟、系統(tǒng)崩潰等意外情況時,將來不及向另一方發(fā)送FIN包,這樣另一方將永遠處于連接狀態(tài)。 可以使用setKeepAlive方法來解決這一個問題
socket.setKeepAlive([enaable],[initialDelay]);
1.2.7 聊天室1.0
/** * 1.創(chuàng)建一個服務(wù)器 * 2. 客戶端可以連接服務(wù)器 * 3.客戶端可以發(fā)言,然后廣播給大家 * 4.客戶端連接和退出后都要通知大家。 * 5.顯示當前的在線人數(shù) */ let net = require('net'); let util = require('util'); let clients = {}; let server = net.createServer(function (socket) { server.getConnections(function (err, count) { socket.write(`weclome,there is ${count} users now,please input your username\r\n`); }); let nickname; socket.setEncoding('utf8'); socket.on('data', function (data) { data = data.replace(/\r\n/, ''); if (data == 'byebye') { socket.end(); } else { if (nickname) { broadcast(nickname, `${nickname}:${data}`); } else { nickname = data; clients[nickname] = socket; broadcast(nickname, `welcome ${nickname} joined us!`); } } }); socket.on('close', function () { socket.destroy(); }); }).listen(8088); function broadcast(nickname, msg) { for (let key in clients) { if (key != nickname) { clients[key].write(msg + '\r\n'); clients[nickname].destroy(); delete clients[nickname]; } } }
1.2.8 聊天室2.0
var key = scoket.remoteAddress+':'+socket.remotePort; users[key] = {name:'匿名',socket}; socket.on('data',function(){ parse(data); }); function parse(msg){ swtich(msg.type){ case 'secret': secret(msg.user,msg.text); break; } case 'boardcast': boardcast(message.text); break; case 'cname': cname(messsage.text); break; case 'list': list(); break; default: socket.write('不能識別命令'); break; } function secret(user,text){ } function boardcast(text){ } function cname(text){ } function list(){ }
b:text 廣播 c:nickname:text 私聊 n:nickname 改名 l 列出在線用戶列表 on('data',function(data){ if(data == 'quit){ }else if(data == 'help'){ }else(){ write(data); } }); function convert(){ }
1.3 類方法
2. UDP
2.1 創(chuàng)建socket
let socket = dgram.createSocket(type,[callback]); socket.on('messsage',function(msg,rinfo){});
socket.bind(port,[address],[callback]); socket.on('listening',callabck;
2.2 向外發(fā)送數(shù)據(jù)
如果發(fā)送數(shù)據(jù)前還沒有綁定過地址和端口號,操作系統(tǒng)將為其分配一個隨機端口并可以接收任何地址的數(shù)據(jù)
socket.send(buf,offset,length,port,address,[callback]);
2.3 address
獲取此socket相關(guān)的地址信息
let address = socket.address();
2.4 UDP服務(wù)器
var dgram = require('dgram'); var socket = dgram.createSocket('udp4'); socket.on('message',function(msg,rinfo){ console.log(msg.toString()); console.log(rinfo); socket.send(msg,0,msg.length,rinfo.port,rinfo.address); }); socket.bind(41234,'localhost');
2.5 UDP客戶端
var dgram = require('dgram'); var socket = dgram.createSocket('udp4'); socket.on('message',function(msg,rinfo){ console.log(msg.toString()); console.log(rinfo); }); socket.setTTL(128); socket.send(new Buffer('zz'),0,6,41234,'localhost',function(err,bytes){ console.log('發(fā)送了個%d字節(jié)',bytes); }); socket.on('error',function(err){ console.error(err); });
2.6 廣播
創(chuàng)建一個UDP服務(wù)器并通過該服務(wù)器進行數(shù)據(jù)的廣播
2.6.1 服務(wù)器
let dgram = require('dgram'); let server = dgram.createSocket('udp4); server.on('message',function(msg){ let buf = new Bufffer('已經(jīng)接收客戶端發(fā)送的數(shù)據(jù)'+msg); server.setBroadcast(true); server.send(buf,0,buf.length,41235,"192.168.1.255"); }); server.bind(41234,'192.168.1.100');
2.6.2 客戶端
let dgram = require('dgram'); let client = dgram.createSocket('udp4); client.bind(41235,'192.168.1.102); let buf = new Buffer('hello'); client.send(buf,0,buf.length,41234,'192.168.1.100'); client.on('message',function(msg,rinfo){ console.log('received : ',msg); });
2.7 組播
所謂的組播,就是將網(wǎng)絡(luò)中同一業(yè)務(wù)類型進行邏輯上的分組,從某個socket端口上發(fā)送的數(shù)據(jù)只能被該組中的其他主機所接收,不被組外的任何主機接收。
實現(xiàn)組播時,并不直接把數(shù)據(jù)發(fā)送給目標地址,而是將數(shù)據(jù)發(fā)送到組播主機,操作系統(tǒng)將把該數(shù)據(jù)組播給組內(nèi)的其他所有成員。
在網(wǎng)絡(luò)中,使用D類地址作為組播地址。范圍是指 224.0.0.0 ~ 239.255.255.255,分為三類
把該socket端口對象添加到組播組中。
socket.addMembership(multicastAddress,[multicastInterface]);
socket.dropMembership(multicastAddress,[multicastInterface]); socket.setMulticastTTL(ttl); socket.setMulticastLoopback(flag);
2.7.1 服務(wù)器
let dgram = require('dgram'); let server = dgram.createSocket('udp4'); server.on('listening',function(){ server.MulticastTTL(128); server.setMulticastLoopback(true); server.addMembership('230.185.192.108'); }); setInterval(broadcast,1000); function broadcast(){ let buffer = Buffer.from(new Date().toLocaleString()); server.send(buffer,0,buffer.length,8080,"230.185.192.108"); }
2.7.2 客戶端
let dgram = require('dgram'); let client = dgram.createSocket('udp4'); client.on('listening',function(){ client.addMembership('230.185.192.108'); }); client.on('message',function(message,remote){ console.log(message.toString()); }); client.bind(8080,'192.168.1.103');
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。