国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > JavaScript > 正文

nodejs實(shí)現(xiàn)套接字服務(wù)功能詳解

2019-11-19 13:37:21
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文實(shí)例講述了nodejs實(shí)現(xiàn)套接字服務(wù)功能。分享給大家供大家參考,具體如下:

一、什么是套接字

1. 套接字允許一個(gè)進(jìn)程他通過(guò)一個(gè)IP地址和端口與另一個(gè)進(jìn)程通信,當(dāng)你實(shí)現(xiàn)對(duì)運(yùn)行在同一臺(tái)服務(wù)器上的兩個(gè)不同進(jìn)程的進(jìn)程間通信或訪問(wèn)一個(gè)完全不同的服務(wù)器上運(yùn)行的服務(wù)時(shí),套接字很有用。node提供的net模塊,允許你既創(chuàng)建套接字服務(wù)器又創(chuàng)建可以連接到套接字服務(wù)器的客戶端。

2. 套接字位于HTTP層下面并提供服務(wù)器之間的點(diǎn)對(duì)點(diǎn)通信。套接字使用套接字地址來(lái)工作,這是IP地址和端口的組合。在套接字連接中,有兩種類型的點(diǎn):一類是服務(wù)器,它監(jiān)聽(tīng)連接;一類是客戶端,它打開(kāi)一個(gè)到服務(wù)器的連接。服務(wù)器和客戶端都需要一個(gè)唯一的IP地址和端口的組合。

3. 套接字是HTTP模塊的底層結(jié)構(gòu),如果你不需要處理如get何post的web請(qǐng)求,只需要點(diǎn)對(duì)點(diǎn)的傳輸數(shù)據(jù),那么使用套接字就可以就能為你提供一個(gè)輕量級(jí)的解決方案和更多的控制。

二、net.Socket對(duì)象

1. Socket對(duì)象同時(shí)在套接字服務(wù)器和客戶端套接字上創(chuàng)建,并允許數(shù)據(jù)在它們之間來(lái)回寫入和讀取。在套接字客戶端,當(dāng)你調(diào)用net.connect()net.createConnection()時(shí),Socket對(duì)象在內(nèi)部創(chuàng)建,這個(gè)對(duì)象是為了表示到服務(wù)器的套接字連接。使用Socket對(duì)象來(lái)監(jiān)控連接,將數(shù)據(jù)發(fā)送到服務(wù)器并處理來(lái)自服務(wù)器的響應(yīng)。在套接字服務(wù)器上,當(dāng)客戶端連接到服務(wù)器時(shí),Socket對(duì)象被創(chuàng)建,并被傳遞到連接事件處理程序,這個(gè)對(duì)象是為了表示對(duì)客戶端的套接字連接。      在NodeJS中有三種socket:TCP,UDP,Unix域套接字,主要介紹NodeJS中TCP的基本編程知識(shí)。

2. 創(chuàng)建一個(gè)Socket對(duì)象,可以使用以下方法:

//第一種方法,通過(guò)一個(gè)options參數(shù)var SocketClient = net.connect(options, [connectionListener]);var SocketClient = net.createConnection(options, [connectionListener]);//第二種方法,通過(guò)接受port和host值作為直接的參數(shù)var SocketClient = net.connect(port, [host], [connectionListener]);var SocketClient = net.createConnection(port, [host], [connectionListener]);//第三種方法,通過(guò)接受指定文件系統(tǒng)位置的path參數(shù),這個(gè)位置是一個(gè)Unix套接字在創(chuàng)建Socket對(duì)象時(shí)使用的。var SocketClient = net.connect(path, [connectionListener]);var SocketClient = net.createConnection(path, [connectionListener]);

無(wú)論你使用哪種,都將返回一個(gè)Socket對(duì)象,唯一的區(qū)別在于接受的第一個(gè)參數(shù),而最后一個(gè)參數(shù)都是當(dāng)連接對(duì)服務(wù)器打開(kāi)時(shí)執(zhí)行的回調(diào)函數(shù)。而無(wú)論你使用net.connect還是net.createConncetion,它們的工作方式是完全相同的。

那么至于第一個(gè)參數(shù),指定的選項(xiàng)為:

port:客戶端應(yīng)連接到的端口。此選項(xiàng)是必需的。
host:客戶端應(yīng)該連接到的服務(wù)器的域名或IP地址。默認(rèn)為localhost
localAddress:客戶端應(yīng)該綁定的用于網(wǎng)絡(luò)連接的本地IP地址。
allowHalfOpen:一個(gè)布爾值,如果為true,則表示當(dāng)套接字的另一端發(fā)送一個(gè)FIN數(shù)據(jù)包時(shí),該套接字將不會(huì)自動(dòng)發(fā)送一個(gè)FIN數(shù)據(jù)包,從而使Duplex流的一半保持開(kāi)放。默認(rèn)為false

3. 一旦Socket對(duì)象被創(chuàng)建,它就提供了在連接到服務(wù)器的生命周期中發(fā)出的幾個(gè)事件,如下:

connect:成功建立與服務(wù)器的連接時(shí)發(fā)出?;卣{(diào)函數(shù)不接受任何參數(shù)
data:在套接字上收到數(shù)據(jù)時(shí)發(fā)出。如果沒(méi)有數(shù)據(jù)時(shí)間處理程序被連接,那么數(shù)據(jù)可能會(huì)丟失。回調(diào)函數(shù)必須接受一個(gè)buffer對(duì)象作為參數(shù),它包含從套接字讀取的數(shù)據(jù)的塊。
end:當(dāng)服務(wù)器通過(guò)發(fā)送一個(gè)FIN終止連接時(shí)發(fā)出。回調(diào)函數(shù)不接受任何參數(shù)
timeout:由于不活動(dòng),因此到服務(wù)器的連接超時(shí)時(shí)發(fā)出。
drain:當(dāng)寫緩沖區(qū)變?yōu)榭諘r(shí)發(fā)出。你可以使用此事件截回被寫入套接字中的數(shù)據(jù)流?;卣{(diào)函數(shù)不接受任何參數(shù)
error:在套接字連接上發(fā)生錯(cuò)誤時(shí)發(fā)出?;卣{(diào)函數(shù)應(yīng)該接受錯(cuò)誤的唯一參數(shù)。
close:套接字已完全關(guān)閉時(shí)發(fā)出,它可能是由一個(gè)end()方法關(guān)閉的,或者因?yàn)榘l(fā)生錯(cuò)誤而關(guān)閉。回調(diào)函數(shù)不接受任何參數(shù)

4. Socket對(duì)象還提供了可以訪問(wèn)以獲得該對(duì)象的信息的幾個(gè)屬性:

bufferSize   當(dāng)前已緩沖并等待寫入套接字的流中的字節(jié)數(shù)
remoteAddress   套接字連接到的遠(yuǎn)程服務(wù)器的IP地址
remotePort    套接字連接到的遠(yuǎn)程服務(wù)器的端口
localAddress   遠(yuǎn)程客戶端用于套接字連接的本地IP地址
localPort     遠(yuǎn)程客戶端用于套接字連接的本地端口
byteRead     由套接字讀取的字節(jié)數(shù)
byteWritten    由套接字寫入的字節(jié)數(shù)

三、net.Server對(duì)象

可以使用net.Server對(duì)象創(chuàng)建一個(gè)TCP套接字服務(wù)器,并監(jiān)聽(tīng)對(duì)它的連接,你將能夠讀取和寫入數(shù)據(jù)。

要?jiǎng)?chuàng)建一個(gè)服務(wù)器獨(dú)享,使用net.createServer()方法:

net.createServer([options],[connectListener])

其中,options是一個(gè)對(duì)象,指定創(chuàng)建套接字Server對(duì)象時(shí)要使用的選項(xiàng),如allowHalfOpen,可以使一半的Duplex流保持開(kāi)放,默認(rèn)為false。connectLlistenerconnection事件的回調(diào)函數(shù),它在接收到連接時(shí)被執(zhí)行。

舉例:

var net = require('net');var HOST = '127.0.0.1';var PORT = 6969;// 創(chuàng)建一個(gè)TCP服務(wù)器實(shí)例,調(diào)用listen函數(shù)開(kāi)始監(jiān)聽(tīng)指定端口// 傳入net.createServer()的回調(diào)函數(shù)將作為”connection“事件的處理函數(shù)// 在每一個(gè)“connection”事件中,該回調(diào)函數(shù)接收到的socket對(duì)象是唯一的net.createServer(function(sock) {  // 我們獲得一個(gè)連接 - 該連接自動(dòng)關(guān)聯(lián)一個(gè)socket對(duì)象  console.log('CONNECTED: ' + sock.remoteAddress + ':' + sock.remotePort);  // 為這個(gè)socket實(shí)例添加一個(gè)"data"事件處理函數(shù)  sock.on('data', function(data) {    console.log('DATA ' + sock.remoteAddress + ': ' + data);    // 回發(fā)該數(shù)據(jù),客戶端將收到來(lái)自服務(wù)端的數(shù)據(jù)    sock.write('You said "' + data + '"');  });  // 為這個(gè)socket實(shí)例添加一個(gè)"close"事件處理函數(shù)  sock.on('close', function(data) {    console.log('CLOSED: ' +      sock.remoteAddress + ' ' + sock.remotePort);  });}).listen(PORT, HOST);console.log('Server listening on ' + HOST +':'+ PORT);

服務(wù)端也可以用稍不同的方式接受TCP連接,即顯式處理"connection"事件:

var server = net.createServer();server.listen(PORT, HOST);console.log('Server listening on ' +  server.address().address + ':' + server.address().port);server.on('connection', function(sock) {  console.log('CONNECTED: ' +     sock.remoteAddress +':'+ sock.remotePort);  // 其它內(nèi)容與前例相同});

上述兩個(gè)例子只是寫法不同,并無(wú)本質(zhì)區(qū)別。

創(chuàng)建TCP客戶端

現(xiàn)在讓我們創(chuàng)建一個(gè)TCP客戶端連接到剛創(chuàng)建的服務(wù)器上,該客戶端向服務(wù)器發(fā)送一串消息,并在得到服務(wù)器的反饋后關(guān)閉連接。下面的代碼描述了這一過(guò)程。

var net = require('net');var HOST = '127.0.0.1';var PORT = 6969;var client = new net.Socket();client.connect(PORT, HOST, function() {  console.log('CONNECTED TO: ' + HOST + ':' + PORT);  // 建立連接后立即向服務(wù)器發(fā)送數(shù)據(jù),服務(wù)器將收到這些數(shù)據(jù)  client.write('I am Chuck Norris!');});// 為客戶端添加“data”事件處理函數(shù)// data是服務(wù)器發(fā)回的數(shù)據(jù)client.on('data', function(data) {  console.log('DATA: ' + data);  // 完全關(guān)閉連接  client.destroy();});// 為客戶端添加“close”事件處理函數(shù)client.on('close', function() {  console.log('Connection closed');});

再舉個(gè)例子:

var net=require('net');function getConnection(connName){  var client=net.connect({port:8017,host:'127.0.0.1'},function(){    console.log(connName+' connected: ');    console.log(' local=%s:%s',this.localAddress,this.localPort);    console.log( ' remote=%s:%s',this.remoteAddress,this.remotePort);    this.setTimeout(500);    this.setEncoding('utf8');    this.on('data',function(data){      console.log(connName+' From Server: '+data.toString());      this.end();    });    this.on('end',function(){      console.log(connName+' Client disnected');    });    this.on('error',function(err){      console.log('Socket Error: ',JSON.stringify(err));    });    this.on('timeout',function(){      console.log('Socket Time Out');    });    this.on('close',function(){      console.log('Socket Closed');    });  });  return client;}function writeData(socket,data){  var success=!socket.write(data);  if(!success){    (function (socket,data){      socket.once('drain',function(){        writeData(socket,data);      });    })(socket,data);  }}var example1=getConnection('example1');var example2=getConnection('example2');writeData(example1,'This is example1');writeData(example2,'This is example2');var server=net.createServer(function(client){  console.log('Client connection: ');  console.log(' local=%s:%s',client.localAddress,client.localPort);  console.log( ' remote=%s:%s',client.remoteAddress,client.remotePort);  client.setTimeout(500);  client.setEncoding('utf8');  client.on('data',function(data){    console.log('Received data from client on port %d:%s',client.remotePort,data.toString());    console.log(' Bytes received:'+data.toString());    writeData(client,'Sending: '+data.toString());    console.log(' Bytes sent: '+client.bytesWritten)  });  client.on('end',function(){    console.log('Client disconnected');    server.getConnections(function(err,count){      console.log('Remaining Connections: '+count);    });  });  client.on('error',function(err){    console.log('Socket Error: '+JSON.stringify(err));  });  client.on('timeout',function(){    console.log('Socket Time Out');  });});server.listen(8017,function(){  console.log('Server listening: '+JSON.stringify(server.address()));  server.on('close',function(){    console.log('Server Terminated');  });  server.on('error',function(err){    console.log('Server Error: ',JSON.stringify(err));  });});

希望本文所述對(duì)大家nodejs程序設(shè)計(jì)有所幫助。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 湖口县| 武鸣县| 高碑店市| 天台县| 西城区| 会理县| 耒阳市| 红安县| 萨迦县| 内江市| 曲阜市| 清河县| 攀枝花市| 来宾市| 高尔夫| 惠来县| 达州市| 抚顺市| 遵义市| 阜宁县| 清流县| 建德市| 景宁| 双江| 延安市| 祁连县| 肥乡县| 纳雍县| 黎川县| 尼玛县| 呼伦贝尔市| 贵阳市| 宾川县| 嘉祥县| 枣庄市| 河北区| 西贡区| 景泰县| 博兴县| 牙克石市| 通道|