モジュール概要
netモジュールは、nodejsのコアモジュールでもあります。 http モジュールの概要で述べたように、http.Server は net.Server を継承します。また、http クライアントと http サーバー間の通信はソケット (net.Socket) に依存します。つまり、ノードサーバープログラミングを行う場合、基本的にnetは避けて通れないモジュールとなります。
構成の観点から見ると、net モジュールは主に 2 つの部分で構成されます。ソケット プログラミングを知っている学生はよく知っているはずです:
net.Server: ソケットを介して内部でクライアントと通信する TCP サーバー。
net.Socket: 全二重ストリームインターフェースを実装する、tcp/ローカルソケットのノードバージョン実装。
この記事は、読者に概要を提供するために、単純な tcp サーバー/クライアントの例から始まります。次に、net.Server と net.Socket のより重要な API、プロパティ、イベントをそれぞれ紹介します。
初心者の場合は、理解を深めるために記事内の例をローカルで実行することをお勧めします。
単純なサーバー + クライアントの例
tcp サーバー プログラムは次のとおりです:
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 クライアントは次のとおりです:
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('你好,我是客户端');
サーバーとクライアントのコードを実行すると、コンソールの出力は次のようになります:
サーバー:
サーバー: クライアントからのリクエストのリッスンを開始します
サーバー: クライアントからリクエストを受信します
サーバー: {こんにちは、私はクライアントです} という内容のクライアント データを受信します
サーバー: クライアント接続が切断されました
クライアント:
クライアント: サーバーとの接続が確立されました
クライアント: サーバー データを受信しました。内容は {こんにちは、サーバーです}
クライアント: 接続が切断されました
サーバー net.Server
server.address()
バインドされた IP アドレス、ポートなどのサーバーのアドレス情報を返します。
console.log( server.address() ); // 输出如下 { port: 3000, family: 'IPv4', address: '127.0.0.1' }
server.close(callback])
サーバーを閉じて、新しいクライアントリクエストの受信を停止します。注意すべき点がいくつかあります:
処理中のクライアントリクエストの場合、サーバーは正式にシャットダウンする前に、リクエストが処理されるまで待機します (またはタイムアウトします)。
通常のシャットダウン中に、コールバックが実行され、close イベントがトリガーされます。
例外が閉じられると、コールバックも実行され、対応するエラーがパラメータとして渡されます。 (たとえば、server.listen(port) が呼び出される前に、server.close() が呼び出されます)
以下は 2 つの具体的な例を通して比較され、結論が最初にリストされます
server.listen() が呼び出されています:正常なシャットダウン、close イベントがトリガーされ、その後コールバックが実行されます。エラー パラメーターは未定義です
server.listen() が呼び出されません。異常なシャットダウン、close イベントがトリガーされ、その後コールバックが実行されます。は特定のエラー メッセージです。 (エラーイベントがトリガーされないことに注意してください)
例 1: サーバーは正常にシャットダウンされます
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 ); });
出力は次のようになります:
close イベント: サーバーがシャットダウンされます
close コールバック: サーバーが正常にシャットダウンされます
例 2: サーバーが異常終了しました
コードは次のとおりです
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 イベント: サーバーが閉じています
close コールバック: サーバー例外: 実行されていません
server.ref()/ server.unref()
ノードのイベント ループを理解している学生であれば、これら 2 つの API は主にイベント ループからサーバーを追加/削除するために使用されます。その影響は、ノードの終了に影響するかどうかにあります。プロセス。
ネットを勉強している学生は特に注意する必要はありません、興味があれば自分で実験してみてください。
イベント listen/connection/close/error
listening: listen リクエストが正式に開始されたときにトリガーされる、server.listen() を呼び出します。
connection: 新しいリクエストが到着するとトリガーされ、パラメータはリクエストに関連するソケットです。
close: サーバーが閉じられるとトリガーされます。
error: すでに占有されているポートの監視など、サービス エラーが発生したときにトリガーされます。
いくつかのイベントは比較的単純です。ここでは接続の例を示します。
テスト結果から、新しいクライアント接続が生成されると net.createServer(callback) のコールバックが呼び出され、接続イベントに登録されたコールバック関数も呼び出されることがわかります。
実際、 net.createServer(callback) のコールバックは、ノードの内部実装の接続イベントのリスニング関数としても追加されています。興味があれば、ノードのソースコードを見てください。
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
出力:
1. 接続トリガー 2. 接続トリガー
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:域名解析完成时触发。