当前位置: 首页 > 后端技术 > Node.js

Nodejs进阶:核心模块net入门及实例讲解

时间:2023-04-03 19:51:19 Node.js

本文节选自《Nodejs学习笔记》,更多章节及更新请访问github主页地址。欢迎加入群交流,群号197339705。模块概述net模块也是nodejs的核心模块。http模块概述中提到,http.Server继承自net.Server。另外,http客户端和http服务器之间的通信依赖于套接字(net.Socket)。也就是说,在做nodeserver编程的时候,net基本是绕不开的模块。从组成上看,net模块主要包括两部分,了解socket编程的同学应该不会陌生:net.Server:TCP服务器,内部通过socket与客户端通信。net.Socket:tcp/localsocket的node版本实现,实现全双工流接口。本文以一个简单的tcpserver/client例子开始,让读者有个大概的了解。然后分别介绍net.Server和net.Socket比较重要的API、属性和事件。对于初学者,建议在本地运行文章中的例子,加深理解。简单服务器+客户端示例tcp服务器程序如下:varnet=require('net');varPORT=3000;varHOST='127.0.0.1';//tcpservervarserver=net.createServer(function(socket){console.log('Server:Receivedrequestfromclient');socket.on('data',function(data){console.log('Server:Receivedclientdata,contentis{'+data+'}');//返回数据给客户端socket.write('你好,我是服务器');});socket.on('close',function(){console.log('Server:clientdisconnected');});});server.listen(PORT,HOST,function(){console.log('服务器:开始监听来自客户端的请求');});tcp客户端如下:varnet=require('net');varPORT=3000;varHOST='127.0.0.1';//tcpclientvarclient=net.createConnection(PORT,HOST);client.on('connect',function(){console.log('client:已与服务器建立连接');});client.on('data',function(data){console.log('client:received到服务器数据,内容为{'+数据+'}');});client.on('close',function(data){console.log('Client:connectiondisconnected');});client.end('您好,我是客户');运行服务端和客户端代码,控制台输出如下:server:server:开始监听来自客户端的请求server:接收来自客户端的请求Server:接收到客户端数据,内容为{你好,我是客户端}Server:客户端断开连接客户端:客户端:已联系服务器服务器建立连接Client:接收服务器数据,内容为{你好,我是服务器}Client:连接断开服务器net.Serverserver.address()返回服务器的地址信息,比如绑定的ip地址、端口等console.log(server.address());//输出结果如下{port:3000,family:'IPv4',address:'127.0.0.1'}server.close(callback])关闭服务器并停止接收新的客户端请求。一些注意事项:对于正在处理的客户端请求,服务器将等待它们被处理(或超时),然后才会正式关闭。正常关机的同时会执行回调,同时触发close事件。当异常关闭时,回调也会被执行,并将相应的错误作为参数传入。(比如server.close()先于server.listen(port)调用。)下面将比较两个具体的例子,先列出结论。Server.listen()已经被调用:正常关机,close事件被触发,然后执行回调。error参数未定义,未调用server.listen():关闭异常,触发close事件,然后执行回调。错误是具体的错误信息。(注意没有触发error事件)例1:服务器正常关闭varnet=require('net');varPORT=3000;varHOST='127.0.0.1';varnoop=function(){};//tcp服务器varserver=net.createServer(noop);server.listen(PORT,HOST,function(){server.close(function(error){if(error){console.log('closecallback:serverexception:'+error.message);}else{console.log('关闭回调:服务器正常关闭');}});});server.on('close',function(){console.log('关闭事件:服务器关闭');});server.on('error',function(error){console.log('错误事件:服务器异常:'+error.message);});输出为:close事件:服务器关闭close回调:服务器正常关闭例2:服务器异常关闭代码如下varnet=require('net');varPORT=3000;varHOST='127.0.0.1';varnoop=function(){};//tcpservervarserver=net.createServer(noop);//没有正式启动请求监听//server.listen(PORT,HOST);server.on('close',function(){console.log('closeevent:serverisclosed');});server.on('error',function(error){console.log('errorevent:serverexception:'+error.message);});server.close(函数(error){if(error){console.log('关闭回调:服务器异常:'+error.message);}else{console.log('关闭回调:服务器正常关闭');}});outputFor:closeevent:serverclosesclosecallback:serverexception:Notrunningserver.ref()/server.unref()了解节点事件循环的同学应该对这两个API不陌生,主要用来添加服务器到事件循环/被移除事件循环,影响是会不会影响进程的退出。对于学习网的同学,没有必要特别注意。如果你有兴趣,就自己做实验吧。事件监听/连接/关闭/错误监听:调用server.listen(),监听请求正式启动时触发。connection:当有新的请求进来时触发,参数是与请求相关的socket。close:服务器关闭时触发。error:当服务出现错误时触发,比如监听一个已经被占用的端口。几个事件比较简单,这里只是一个连接的例子。从测试结果可以看出,当产生新的客户端连接时,会调用net.createServer(callback)中的callback回调,同时也会调用connection事件中注册的回调函数。其实net.createServer(callback)中的回调也是在node内部实现中作为连接事件的监听函数加入的。有兴趣的可以看看node的源码。varnet=require('net');varPORT=3000;varHOST='127.0.0.1';varnoop=function(){};//tcp服务器varserver=net.createServer(function(socket){socket.write('1.连接触发\n');});server.on('连接',function(socket){socket.end('2.连接触发\n');});server.listen(端口、主机);使用如下命令测试curlhttp://127.0.0.1:3000的效果输出:1.连接触发2.连接触发客户端net.Socket在文章开头已经给出了客户端的例子,以及在这里我们放了例子贴。(备注:严格来说net.Socket不应该叫做client,这里只是为了方便说明。)从node的官方文档来看,感觉net.Socket比net.Server复杂多了API、事件、属性。但实际上,如果将net.Socket相关的API、事件、属性进行分类,就会发现它们并不是特别复杂。有关详细信息,请参阅下一节。varnet=require('net');varPORT=3000;varHOST='127.0.0.1';//tcp客户端varclient=net.createConnection(PORT,HOST);client.on('connect',function(){console.log('client:已与服务器建立连接');});client.on('data',function(data){console.log('client:收到服务器数据,内容为{'+data+'}');});client.on('close',function(data){console.log('Client:connectiondisconnected');});client.end('你好,我是客户');API和属性分类net.Socket的API和属性按照用途大致分类一下,方便读者更好的理解。大部分API和属性都比较简单,看了文档就知道怎么做了,这里就不展开了。连接相关的socket.connect():针对不同的场景,有3个不同的参数;socket.setTimeout():用于设置连接超时时间。socket.setKeepAlive():用于建立长连接。socket.destroy()、socket.destroyed:当发生错误时,用于销毁socket,保证不会有其他IO操作在这个socket上。数据读写相关socket.write(),socket.end(),socket.pause(),socket.resume(),socket.setEncoding(),socket.setNoDelay()数据属性相关socket.bufferSize,socket.bytesRead,socket.bytesWritteneventlooprelatedsocket.ref(),socket.unref()addressrelatedsocket.address()socket.remoteAddress,socket.remoteFamily,socket.remotePortsocket.localAddress/socket.localPort事件配置文件数据:当另一个被触发当数据来自一侧时。connect:建立连接时触发。close:连接断开时触发。如果由于传输错误而断开连接,则该参数错误。end:当连接的另一端发送FIN包时触发(读者可以回顾一下HTTP是如何断开连接的)。默认情况下(allowHalfOpen==false),套接字会完成自毁操作。但是也可以将allowHalfOpen设置为true,这样就可以继续往socket中写入数据。当然最后还需要手动调用socket.end()error:当发生错误时,才会触发,参数为error。(官方文档基本一句话都提到了,不过考虑到可能错误太多,可以理解)timeout:提示用户socket超时,需要手动关闭连接。drain:写缓存为空时触发。(不太好描述,详见stream的介绍)lookup:域名解析完成时触发。相关链接官方文档:https://nodejs.org/api/net.ht...