모듈 개요
net 모듈은 nodejs의 핵심 모듈이기도 합니다. http 모듈 개요에서 언급했듯이 http.Server는 net.Server를 상속합니다. 또한 http 클라이언트와 http 서버 간의 통신은 소켓(net.Socket)에 의존합니다. 즉, 노드 서버 프로그래밍을 할 때 net은 기본적으로 빼놓을 수 없는 모듈이다.
구성적인 관점에서 net 모듈은 크게 두 부분으로 구성됩니다. 소켓 프로그래밍을 아는 학생이라면 익숙할 것입니다.
net.Server: 네트워크와 통신하는 TCP 서버입니다. 소켓을 통해 내부적으로 클라이언트.
net.Socket: 전이중 스트림 인터페이스를 구현하는 tcp/local 소켓의 노드 버전 구현입니다.
이 기사는 독자에게 개요를 제공하기 위한 간단한 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('你好,我是客户端');
실행 server, 클라이언트 코드, 콘솔 출력은 다음과 같습니다.
서버:
서버: 클라이언트의 요청 수신 대기 시작
서버: 클라이언트에서 요청 수신
서버: 수신된 클라이언트 데이터, 내용은 {안녕하세요, 저는 클라이언트입니다}
서버: 클라이언트 연결 끊김
클라이언트:
클라이언트 클라이언트: 연결이 설정되었습니다. server
클라이언트: 서버로부터 데이터를 받았습니다. 내용은 {안녕하세요, 저는 서버입니다}
클라이언트: 연결이 끊어졌습니다
Service Net.Server
server.address()
는 바인딩된 IP 주소, 포트 등 서버의 주소 정보를 반환합니다.
console.log( server.address() ); // 输出如下 { port: 3000, family: 'IPv4', address: '127.0.0.1' }
server.close(callback])
서버를 닫고 새 클라이언트 요청 수신을 중지합니다. 몇 가지 참고할 사항이 있습니다:
처리 중인 클라이언트 요청의 경우 서버는 공식적으로 종료되기 전에 해당 요청이 처리될 때까지(또는 시간 초과될 때까지 기다립니다).
정상 종료 중에는 콜백이 실행되고 닫기 이벤트가 트리거됩니다.
예외가 종료되면 콜백도 실행되며 해당 오류가 매개변수로 전달됩니다. (예를 들어 server.listen(port)이 호출되기 전에 server.close()가 호출됩니다.)
다음은 구체적인 두 가지 예를 통해 비교하고 결론을 먼저 나열하겠습니다
Server.listen()이 호출되었습니다: 정상 종료, 닫기 이벤트가 트리거된 후 콜백이 실행되고 오류 매개변수가 정의되지 않았습니다
Server.listen()이 호출되지 않았습니다: 비정상 종료, 닫기 이벤트가 트리거된 후 콜백이 실행되고 오류는 특정 오류 메시지입니다. (오류 이벤트는 발생하지 않습니다.)
예 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 callback : 서버가 정상적으로 종료된 경우
예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()
노드 이벤트 루프를 이해하는 학생들은 다음 두 가지 질문을 가지고 있습니다. 이 API는 주로 이벤트 루프에서 서버를 추가/제거하는 데 사용됩니다. 영향은 노드 종료에 영향을 미칩니다. 프로세스.
넷을 공부하는 학생들은 특별히 주의할 필요는 없습니다. 관심이 있다면 직접 실험해 보세요.
이벤트 청취/연결/닫기/오류
listening: server.listen()을 호출하고, 청취 요청이 공식적으로 시작될 때 트리거됩니다.
connection: 새로운 요청이 들어올 때 트리거되며, 매개변수는 요청과 관련된 소켓입니다.
close: 서버가 닫힐 때 트리거됩니다.
오류: 이미 사용 중인 포트를 모니터링하는 등 서비스 오류가 발생할 때 트리거됩니다.
몇 가지 이벤트는 비교적 간단합니다. 연결의 예는 다음과 같습니다.
테스트 결과를 보면 새로운 클라이언트 연결이 발생하면 net.createServer(callback)에 있는 콜백이 호출되고, 연결 이벤트에 등록된 콜백 함수도 호출되는 것을 알 수 있습니다.
실제로 net.createServer(callback)의 콜백도 노드 내부 구현에서 연결 이벤트에 대한 수신 함수로 추가됩니다. 관심이 있으시면 node.js의 소스 코드를 살펴보세요.
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. 연결 트리거
클라이언트 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:域名解析完成时触发。