Heim  >  Artikel  >  Web-Frontend  >  Nodejs für Fortgeschrittene: Erste Schritte mit dem Kernmodul „net“ und Erläuterung anhand von Beispielen

Nodejs für Fortgeschrittene: Erste Schritte mit dem Kernmodul „net“ und Erläuterung anhand von Beispielen

高洛峰
高洛峰Original
2016-11-17 10:18:511148Durchsuche

Modulübersicht

net-Modul ist auch das Kernmodul von nodejs. Wie in der Übersicht über das http-Modul erwähnt, erbt http.Server net.Server. Darüber hinaus basiert die Kommunikation zwischen dem http-Client und dem http-Server auf Socket (net.Socket). Mit anderen Worten, bei der Node-Server-Programmierung ist net grundsätzlich ein Modul, das nicht vermieden werden kann.

Aus kompositorischer Sicht besteht das Netzmodul hauptsächlich aus zwei Teilen. Studierende, die sich mit der Socket-Programmierung auskennen, sollten damit vertraut sein:

net.Server: TCP-Server, der mit dem kommuniziert Client intern über Sockets.

net.Socket: Die Knotenversionsimplementierung von TCP/Local Socket, die die Vollduplex-Stream-Schnittstelle implementiert.

Dieser Artikel beginnt mit einem einfachen TCP-Server/Client-Beispiel, um den Lesern ein allgemeines Verständnis zu vermitteln. Anschließend stellen wir die wichtigeren APIs, Eigenschaften und Ereignisse von net.Server bzw. net.Socket vor.

Für Anfänger wird empfohlen, die Beispiele im Artikel lokal auszuführen, um ihr Verständnis zu vertiefen.

Ein einfaches Server-Client-Beispiel

TCP-Serverprogramm lautet wie folgt:

var net = require('net');

var PORT = 3000;
var HOST = '127.0.0.1';

// tcp服务端
var server = net.createServer(function(socket){
    console.log('服务端:收到来自客户端的请求');

    socket.on('data', function(data){
        console.log('服务端:收到客户端数据,内容为{'+ data +'}');

        // 给客户端返回数据
        socket.write('你好,我是服务端');
    });

    socket.on('close', function(){
         console.log('服务端:客户端连接断开');
    });
});
server.listen(PORT, HOST, function(){
    console.log('服务端:开始监听来自客户端的请求');
});

TCP-Client lautet wie folgt:

var net = require('net');

var PORT = 3000;
var HOST = '127.0.0.1';

// tcp客户端
var client = net.createConnection(PORT, HOST);

client.on('connect', function(){
    console.log('客户端:已经与服务端建立连接');
});

client.on('data', function(data){
    console.log('客户端:收到服务端数据,内容为{'+ data +'}');
});

client.on('close', function(data){
    console.log('客户端:连接断开');
});

client.end('你好,我是客户端');

Führen Sie das aus Server, Der Client-Code und die Konsolenausgabe lauten wie folgt:

Server:

Server: Auf Anfragen vom Client warten
Server: Anfragen vom Client empfangen
Service-Client : Empfangene Client-Daten, der Inhalt lautet {Hallo, ich bin der Client}. 🎜>Server: Client-Verbindung getrennt

Client:

Client: Es wurde eine Verbindung mit dem hergestellt Server

Client: Serverdaten empfangen, der Inhalt ist {Hallo, ich bin der Server🎜>Client: Die Verbindung ist getrennt


Server net.Server

Server .address()

gibt die Adressinformationen des Servers zurück, wie z. B. die gebundene IP-Adresse, den Port usw.

server.close(callback])
console.log( server.address() );
// 输出如下 { port: 3000, family: 'IPv4', address: '127.0.0.1' }

Schließen Sie den Server und empfangen Sie keine neuen Clientanfragen mehr. Es gibt ein paar Dinge zu beachten:

Bei Client-Anfragen, die verarbeitet werden, wartet der Server auf deren Verarbeitung (oder Zeitüberschreitung), bevor er offiziell heruntergefahren wird.

Während des normalen Herunterfahrens wird der Rückruf ausgeführt und das Schließereignis ausgelöst.

Wenn die Ausnahme geschlossen ist, wird auch der Rückruf ausgeführt und der entsprechende Fehler als Parameter übergeben. (Zum Beispiel wird server.close() aufgerufen, bevor server.listen(port) aufgerufen wird)

Das Folgende wird anhand zweier spezifischer Beispiele verglichen und die Schlussfolgerungen werden zuerst aufgeführt

Server.listen() wurde aufgerufen: normales Herunterfahren, das Schließereignis wird ausgelöst und dann wird der Rückruf ausgeführt und der Fehlerparameter ist undefiniert

Server.listen() wurde nicht aufgerufen: abnormales Herunterfahren, Das Schließereignis wird ausgelöst, dann wird der Rückruf ausgeführt und der Fehler ist Spezifische Fehlermeldung. (Beachten Sie, dass das Fehlerereignis nicht ausgelöst wird)

Beispiel 1: Der Server ist normal geschlossen

Die Ausgabe lautet:
var net = require('net');
var PORT = 3000;
var HOST = '127.0.0.1';
var noop = function(){};

// tcp服务端
var server = net.createServer(noop);

server.listen(PORT, HOST, function(){

    server.close(function(error){
        if(error){
            console.log( 'close回调:服务端异常:' + error.message );
        }else{
            console.log( 'close回调:服务端正常关闭' );
        }            
    }); 
});

server.on('close', function(){
    console.log( 'close事件:服务端关闭' );
});

server.on('error', function(error){
    console.log( 'error事件:服务端异常:' + error.message );
});

Schließereignis: Der Server ist geschlossen

Rückruf schließen: Der Server wird normal heruntergefahren



Beispiel 2: Der Server wird abnormal heruntergefahren

Der Code lautet wie folgt

Die Ausgabe ist:
var net = require('net');
var PORT = 3000;
var HOST = '127.0.0.1';
var noop = function(){};

// tcp服务端
var server = net.createServer(noop);

// 没有正式启动请求监听
// server.listen(PORT, HOST);

server.on('close', function(){
    console.log( 'close事件:服务端关闭' );
});

server.on('error', function(error){
    console.log( 'error事件:服务端异常:' + error.message );
});

server.close(function(error){
    if(error){
        console.log( 'close回调:服务端异常:' + error.message );
    }else{
        console.log( 'close回调:服务端正常关闭' );
    }            
});

Close-Ereignis: Server schließt

Callback schließen: Serverseitige Ausnahme: Wird nicht ausgeführt



server.ref()/server.unref()

Studenten, die die Knoten-Ereignisschleife verstehen, haben diese beiden Fragen. Diese API sollte Ihnen bekannt sein. Sie wird hauptsächlich zum Hinzufügen/Entfernen des Servers zur Ereignisschleife verwendet Verfahren.

Für Studierende, die online lernen, ist keine besondere Aufmerksamkeit erforderlich. Wenn Sie interessiert sind, führen Sie das Experiment einfach selbst durch.

Ereignis Abhören/Verbindung/Schließen/Fehler

Abhören: Rufen Sie server.listen() auf, ausgelöst, wenn die Abhöranforderung offiziell gestartet wird.

Verbindung: Wird ausgelöst, wenn eine neue Anfrage eingeht. Der Parameter ist der Socket, der sich auf die Anfrage bezieht.

Schließen: Wird ausgelöst, wenn der Server geschlossen wird.

Fehler: Wird ausgelöst, wenn ein Dienstfehler auftritt, beispielsweise bei der Überwachung eines Ports, der bereits belegt ist.

Einige Ereignisse sind relativ einfach. Hier ist nur ein Beispiel für den Zusammenhang.

Aus den Testergebnissen geht hervor, dass beim Generieren einer neuen Clientverbindung der Rückruf in net.createServer(callback) aufgerufen wird und auch die für das Verbindungsereignis registrierte Rückruffunktion aufgerufen wird.

Tatsächlich wird der Rückruf in net.createServer(callback) auch als Überwachungsfunktion für das Verbindungsereignis in der internen Implementierung des Knotens hinzugefügt. Wenn Sie interessiert sind, können Sie sich den Quellcode von node ansehen.

Testen Sie den Effekt mit dem folgenden Befehl
var net = require('net');
var PORT = 3000;
var HOST = '127.0.0.1';
var noop = function(){};

// tcp服务端
var server = net.createServer(function(socket){
    socket.write('1. connection 触发\n');
});

server.on('connection', function(socket){
    socket.end('2. connection 触发\n');
});

server.listen(PORT, HOST);

curl http://127.0.0.1:3000


Ausgabe:

1 . Verbindungsauslöser 2. Verbindungsauslöser


Client net.Socket

在文章开头已经举过客户端的例子,这里再把例子贴一下。(备注:严格来说不应该把 net.Socket 叫做客户端,这里方便讲解而已)

单从node官方文档来看的话,感觉 net.Socket 比 net.Server 要复杂很多,有更多的API、事件、属性。但实际上,把 net.Socket 相关的API、事件、属性 进行归类下,会发现,其实也不是特别复杂。

具体请看下一小节内容。

var net = require('net');

var PORT = 3000;
var HOST = '127.0.0.1';

// tcp客户端
var client = net.createConnection(PORT, HOST);

client.on('connect', function(){
    console.log('客户端:已经与服务端建立连接');
});

client.on('data', function(data){
    console.log('客户端:收到服务端数据,内容为{'+ data +'}');
});

client.on('close', function(data){
    console.log('客户端:连接断开');
});

client.end('你好,我是客户端');

API、属性归类

以下对net.Socket的API跟属性,按照用途进行了大致的分类,方便读者更好的理解。大部分API跟属性都比较简单,看下文档就知道做什么的,这里就先不展开。

连接相关

socket.connect():有3种不同的参数,用于不同的场景;

socket.setTimeout():用来进行连接超时设置。

socket.setKeepAlive():用来设置长连接。

socket.destroy()、socket.destroyed:当错误发生时,用来销毁socket,确保这个socket上不会再有其他的IO操作。

数据读、写相关

socket.write()、socket.end()、socket.pause()、socket.resume()、socket.setEncoding()、socket.setNoDelay()

数据属性相关

socket.bufferSize、socket.bytesRead、socket.bytesWritten

事件循环相关

socket.ref()、socket.unref()

地址相关

socket.address()

socket.remoteAddress、socket.remoteFamily、socket.remotePort

socket.localAddress/socket.localPort

事件简介

data:当收到另一侧传来的数据时触发。

connect:当连接建立时触发。

close:连接断开时触发。如果是因为传输错误导致的连接断开,则参数为error。

end:当连接另一侧发送了 FIN 包的时候触发(读者可以回顾下HTTP如何断开连接的)。默认情况下(allowHalfOpen == false),socket会完成自我销毁操作。但你也可以把 allowHalfOpen 设置为 true,这样就可以继续往socket里写数据。当然,最后你需要手动调用 socket.end()

error:当有错误发生时,就会触发,参数为error。(官方文档基本一句话带过,不过考虑到出错的可能太多,也可以理解)

timeout:提示用户,socket 已经超时,需要手动关闭连接。

drain:当写缓存空了的时候触发。(不是很好描述,具体可以看下stream的介绍)

lookup:域名解析完成时触发。


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn