nodejs 實現套接字服務


nodejs實現套接字服務
 
 
一 什么是套接字
1.套接字允許一個進程他通過一個IP地址和端口與另一個進程通信,當你實現對運行在同一台服務器上的兩個不同進程的進程間通信或訪問一個完全不同的服務器上運行的服務時,套接字很有用。node提供的net模塊,允許你既創建套接字服務器又創建可以連接到套接字服務器的客戶端。
2.套接字位於HTTP層下面並提供服務器之間的點對點通信。套接字使用套接字地址來工作,這是IP地址和端口的組合。在套接字連接中,有兩種類型的點:一類是服務器,它監聽連接;一類是客戶端,它打開一個到服務器的連接。服務器和客戶端都需要一個唯一的IP地址和端口的組合。
3.套接字是HTTP模塊的底層結構,如果你不需要處理如get何post的web請求,只需要點對點的傳輸數據,那么使用套接字就可以就能為你提供一個輕量級的解決方案和更多的控制。                                                                                                                                                                                                                                                                                                                                                                                                                                    二  net.Socket對象
1.Socket對象同時在套接字服務器和客戶端套接字上創建,並允許數據在它們之間來回寫入和讀取。在套接字客戶端,當你調用net.connect()或net.createConnection()時,Socket對象在內部創建,這個對象是為了表示到服務器的套接字連接。使用Socket對象來監控連接,將數據發送到服務器並處理來自服務器的響應。在套接字服務器上,當客戶端連接到服務器時,Socket對象被創建,並被傳遞到連接事件處理程序,這個對象是為了表示對客戶端的套接字連接。      在NodeJS中有三種socket:TCP,UDP,Unix域套接字,主要介紹NodeJS中TCP的基本編程知識。
 
2.創建一個Socket對象,可以使用以下方法:
//第一種方法,通過一個options參數
var SocketClient = net.connect(options, [connectionListener]);
var SocketClient = net.createConnection(options, [connectionListener]);
 
//第二種方法,通過接受port和host值作為直接的參數
var SocketClient = net.connect(port, [host], [connectionListener]);
var SocketClient = net.createConnection(port, [host], [connectionListener]);
 
//第三種方法,通過接受指定文件系統位置的path參數,這個位置是一個Unix套接字在創建Socket對象時使用的。
var SocketClient = net.connect(path, [connectionListener]);
var SocketClient = net.createConnection(path, [connectionListener]);
無論你使用哪種,都將返回一個Socket對象,唯一的區別在於接受的第一個參數,而最后一個參數都是當連接對服務器打開時執行的回調函數。而無論你使用net.connect還是net.createConncetion,它們的工作方式是完全相同的。
那么至於第一個參數,指定的選項為:
port:客戶端應連接到的端口。此選項是必需的。
host:客戶端應該連接到的服務器的域名或IP地址。默認為localhost
localAddress:客戶端應該綁定的用於網絡連接的本地IP地址。
allowHalfOpen:一個布爾值,如果為true,則表示當套接字的另一端發送一個FIN數據包時,該套接字將不會自動發送一個FIN數據包,從而使Duplex流的一半保持開放。默認為false
 
3.一旦Socket對象被創建,它就提供了在連接到服務器的生命周期中發出的幾個事件,如下:
connect:成功建立與服務器的連接時發出。回調函數不接受任何參數
data:在套接字上收到數據時發出。如果沒有數據時間處理程序被連接,那么數據可能會丟失。回調函數必須接受一個buffer對象作為參數,它包含從套接字讀取的數據的塊。
end:當服務器通過發送一個FIN終止連接時發出。回調函數不接受任何參數
timeout:由於不活動,因此到服務器的連接超時時發出。
drain:當寫緩沖區變為空時發出。你可以使用此事件截回被寫入套接字中的數據流。回調函數不接受任何參數
error:在套接字連接上發生錯誤時發出。回調函數應該接受錯誤的唯一參數。
close:套接字已完全關閉時發出,它可能是由一個end()方法關閉的,或者因為發生錯誤而關閉。回調函數不接受任何參數
 
5.Socket對象還提供了可以訪問以獲得該對象的信息的幾個屬性:
bufferSize   當前已緩沖並等待寫入套接字的流中的字節數
remoteAddress   套接字連接到的遠程服務器的IP地址
remotePort    套接字連接到的遠程服務器的端口
localAddress   遠程客戶端用於套接字連接的本地IP地址
localPort     遠程客戶端用於套接字連接的本地端口
byteRead     由套接字讀取的字節數
byteWritten    由套接字寫入的字節數
 
三 net.Server對象
可以使用net.Server對象創建一個TCP套接字服務器,並監聽對它的連接,你將能夠讀取和寫入數據。
要創建一個服務器獨享,使用net.createServer()方法:
net.createServer([options],[connectListener])
其中,options是一個對象,指定創建套接字Server對象時要使用的選項,如allowHalfOpen,可以使一半的Duplex流保持開放,默認為false。connectLlistener是connection事件的回調函數,它在接收到連接時被執行。
 
舉例:
var net = require('net');
var HOST = '127.0.0.1';
var PORT = 6969;
 
// 創建一個TCP服務器實例,調用listen函數開始監聽指定端口
// 傳入net.createServer()的回調函數將作為”connection“事件的處理函數
// 在每一個“connection”事件中,該回調函數接收到的socket對象是唯一的
net.createServer(function(sock) {
 
    // 我們獲得一個連接 - 該連接自動關聯一個socket對象
    console.log('CONNECTED: ' + sock.remoteAddress + ':' + sock.remotePort);
 
    // 為這個socket實例添加一個"data"事件處理函數
    sock.on('data', function(data) {
        console.log('DATA ' + sock.remoteAddress + ': ' + data);
        // 回發該數據,客戶端將收到來自服務端的數據
        sock.write('You said "' + data + '"');
    });
 
    // 為這個socket實例添加一個"close"事件處理函數
    sock.on('close', function(data) {
        console.log('CLOSED: ' +
            sock.remoteAddress + ' ' + sock.remotePort);
    });
 
}).listen(PORT, HOST);
console.log('Server listening on ' + HOST +':'+ PORT);
服務端也可以用稍不同的方式接受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);
    // 其它內容與前例相同
});
上述兩個例子只是寫法不同,並無本質區別。
 
創建TCP客戶端
現在讓我們創建一個TCP客戶端連接到剛創建的服務器上,該客戶端向服務器發送一串消息,並在得到服務器的反饋后關閉連接。下面的代碼描述了這一過程。
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);
    // 建立連接后立即向服務器發送數據,服務器將收到這些數據
    client.write('I am Chuck Norris!');
});
 
// 為客戶端添加“data”事件處理函數
// data是服務器發回的數據
client.on('data', function(data) {
    console.log('DATA: ' + data);
    // 完全關閉連接
    client.destroy();
});
 
// 為客戶端添加“close”事件處理函數
client.on('close', function() {
    console.log('Connection closed');
});

 

 
再舉個例子:
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));
    });
});

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM