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 einen Überblick zu geben. 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.
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, Client-Code, die Konsolenausgabe lautet wie folgt:
Server:
Server: Auf Anfragen vom Client warten
Server: Anfragen vom Client empfangen
Server: Empfangene Client-Daten, der Inhalt lautet {Hallo, ich bin der Client}.🎜>Server: Client-Verbindung getrennt
Client: Daten vom Server empfangen, der Inhalt ist {Hallo, ich bin der Server🎜>Client: Die Verbindung ist getrennt
Service Net.Server
server.address()
gibt die Adressinformationen des Servers zurück, wie z. B. die gebundene IP-Adresse, den Port usw.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)
Im Folgenden werden zwei spezifische Beispiele verglichen und zunächst die Schlussfolgerungen aufgeführt
Server. listen() wurde aufgerufen: normales Herunterfahren, das Schließereignis wird ausgelöst und dann wird der Rückruf ausgeführt. Der Fehlerparameter ist undefiniert
server.listen() wird nicht aufgerufen: abnormales Herunterfahren, das Schließereignis ist ausgelöst und dann der Rückruf ausgeführt wird, ist „error“ die spezifische Fehlermeldung. (Beachten Sie, dass das Fehlerereignis nicht ausgelöst wird)
Beispiel 1: Der Server wird normal heruntergefahren
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 wird heruntergefahren
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回调:服务端正常关闭' ); } });
Ereignis schließen: Server ist geschlossen
Rückruf schließen: Serverausnahme: Läuft nicht
server.ref()/server.unref ()
Studenten sollten mit diesen beiden APIs vertraut sein. Sie werden hauptsächlich zum Hinzufügen/Entfernen des Servers zur Ereignisschleife verwendet der Prozess.
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.
Mehrere 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 Befehlvar 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
Das Beispiel des Clients wurde am Anfang des Artikels angegeben und ich werde das Beispiel veröffentlichen Hier. (Anmerkungen: Streng genommen sollte net.Socket nicht als Client bezeichnet werden. Es ist nur praktisch, es hier zu erklären.)
Nach der offiziellen Knotendokumentation zu urteilen, bin ich der Meinung, dass net.Socket viel komplizierter ist als net .Server, und es gibt noch mehr Multiple APIs, Ereignisse und Eigenschaften. Wenn Sie jedoch die mit net.Socket verbundenen APIs, Ereignisse und Eigenschaften klassifizieren, werden Sie feststellen, dass dies nicht besonders kompliziert ist.
Weitere Informationen finden Sie im nächsten Abschnitt.
API- und Attributklassifizierungvar 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('你好,我是客户端');
Die folgenden APIs und Attribute von net.Socket werden grob nach ihrer Verwendung klassifiziert, um den Lesern ein besseres Verständnis zu erleichtern. Die meisten APIs und Eigenschaften sind relativ einfach. Sie werden wissen, was sie tun, wenn Sie die Dokumentation lesen, daher werde ich sie hier nicht näher erläutern.
Verbindungsbezogen
socket.connect(): Es gibt 3 verschiedene Parameter, die in verschiedenen Szenarien verwendet werden;
socket.setTimeout(): wird zum Festlegen des Verbindungszeitlimits verwendet.
socket.setKeepAlive(): wird zum Festlegen einer langen Verbindung verwendet.
socket.destroy(), socket.destroyed: Wird verwendet, um den Socket zu zerstören, wenn ein Fehler auftritt, um sicherzustellen, dass auf diesem Socket keine anderen E/A-Vorgänge ausgeführt werden.
Bezogen auf das Lesen und Schreiben von Daten
socket.write(), socket.end(), socket.pause(), socket.resume(), socket.setEncoding(), socket.setNoDelay()
Datenattributbezogen
socket.bufferSize, socket.bytesRead, socket.bytesWritten
Ereignisschleifenbezogen
socket.ref(), socket.unref()
Adressbezogen
socket.address()
socket.remoteAddress, socket.remoteFamily, socket.remotePort
socket.localAddress/socket.localPort
Ereigniseinführung
Daten: Wird ausgelöst, wenn Daten von der anderen Seite empfangen werden.
connect: Wird ausgelöst, wenn die Verbindung hergestellt ist.
Schließen: Wird ausgelöst, wenn die Verbindung getrennt wird. Wenn die Verbindung aufgrund eines Übertragungsfehlers getrennt wird, ist der Parameter fehlerhaft.
Ende: Wird ausgelöst, wenn die andere Seite der Verbindung ein FIN-Paket sendet (Leser können sehen, wie HTTP die Verbindung trennt). Standardmäßig (allowHalfOpen == false) schließt der Socket den Selbstzerstörungsvorgang ab. Sie können aber auch „allowHalfOpen“ auf „true“ setzen, sodass Sie weiterhin Daten in den Socket schreiben können. Am Ende müssen Sie natürlich socket.end()
error manuell aufrufen: Es wird ausgelöst, wenn ein Fehler auftritt, und der Parameter ist error. (Das offizielle Dokument erwähnt es grundsätzlich in einem Satz, aber wenn man bedenkt, dass es möglicherweise zu viele Fehler gibt, ist es verständlich)
Timeout: Fordert den Benutzer auf, dass der Socket abgelaufen ist und die Verbindung manuell geschlossen werden muss .
Drain: Wird ausgelöst, wenn der Schreibcache leer ist. (Es ist nicht sehr beschreibend, Sie können die Einführung im nächsten Stream für Details lesen)
Suche: Wird ausgelöst, wenn die Auflösung des Domainnamens abgeschlossen ist.