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

Node.js网络通信模块浅析

时间:2023-04-03 11:44:49 Node.js

前言想必我们最常使用Node.js来创建http服务,所以对于每一个Web开发工程师来说,学习Node.js网络相关模块是必不可少的。Node.js的网络模块架构在Node.js模块中。网络相关模块包括Net、DNS、HTTP、TLS/SSL、HTTPS、UDP/Datagram。此外,还有v8底层相关的网络模块有tcp_wrap.cc、udp_wrap.cc、pipe_wrap.cc、stream_wrap.cc等,它们通过process.binding在Javascript层和C++层。Net模块Net模块提供了一些低级的网络通信接口,包括创建服务器和客户端。HTTP模块也是基于Net模型的上层封装。Net模块主要提供net.Server和net.Socket来创建TCP服务器。要创建TCP服务器,可以使用构造函数newnet.Server或使用工厂方法net.createServer。这两种方法都将返回一个可以接收两个可选参数的net.Server类。varnet=require('net');varserver=net.createServer(function(socket){socket.on('data',function(data){console.log('socketdata',data.toString());socket.write(data.toString());}).on('end',function(){console.log('socketend')}).on('error',function(error){console.log('socketerror',error);});});server.listen(56200,function(){console.log('serverrunat',server.address());});server.on('error',function(err){throwerr;});//执行后:serverrunat{address:'::',family:'IPv6',port:56200}如果监听时没有指定端口就会随意自动监听一个端口。创建TCP服务器后,连接后使用tenlent0.0.0.056200与服务器通信。通过createServer实例化一个服务后,该服务会监听客户端的请求,并在与客户端建立连接后,在回调中抛出net.Socket对象。创建TCP客户端要创建TCP客户端连接,可以使用构造函数newnet.Socket或其工厂方法net.createConnection。创建成功后,会返回一个net.Socket实例。varnet=require('net');varclient=net.createConnection({port:56200,host:'localhost'});client.on('connect',function(){console.log('clientconnect');});client.on('data',function(data){console.log('clientdata',toString());});client.on('error',function(error){抛出错误;});client.on('close',function(){console.log('clientclose');});什么是Socketsocket?这里我就不细说了。下面主要了解一下net.Socket的结构,body主要提供了一些方法和监听事件的使用。相关事件connect:当客户端与服务端成功建立连接时触发。如果连接失败,服务端直接抛出错误事件并退出节点进程。data:客户端收到服务端发送的数据或客户端向服务端发送的数据时触发回调。end:当对方发送的FIN包断开连接时触发。默认情况下(allowHalfOpen==false)socket会自毁(如果写入pending队列还没有正式响应数据包),但是我们可以设置allowHalfOpen参数为true,就可以继续写了数据写入socket,但是我们需要调用end方法来消费socket,否则可能会造成句柄泄露。close:链接断开时触发,但如果传输过程中出现错误,回调函数中会抛出错误。timeout:套接字超时空闲时触发。如果想在队列中销毁,需要手动调整close方法。lookup:域名解析完成时触发。drain:写入缓冲区时触发,可用于上传大小限制。相关方法write():服务端向客户端发送数据或客户端向服务端发送数据。address():获取服务绑定的套接字IP地址。返回的对象具有三个属性,分别是端口、主机和IPvX版本。end():半关闭套接字,会发送一个FIN包,服务器可能还会发送一些数据,你也可以这样调用socket.end(data,encoding)。pause():暂停读取数据,可以作为数据上传的限制。resume():继续读取数据。setEncoding():设置数据流的获取格式。setKeepAlive():启用/禁用保活功能。setNoDelay():禁用Nagele算法,TCP连接默认使用Nagele算法,它们的数据在发送前会缓存起来。如果为true,则每次socket.write()都会立即发送数据,默认为true。setTimeout():idlesocket在多少秒后不活动时会收到超时事件,但socket不会停止销毁,需要手动调用end()或destroy()。指示空闲超时已禁用。相关属性bufferSize:当前缓冲等待发送的字符串数。bytesRead:接收到的字节数。bytesWritten:Thenumberofbytessentdestroyed:表示链接是否已经被破坏,一旦破坏,不要使用该链接传输数据。localAddress:远程客户端连接到主机的本地地址。如果我们监听服务的host是0.0.0.0,clientconnection是'192.168.1.1',最后的值就是后者。localPort:本地端口。remoteAddress:客户端IP,如果socket被destryed,则该值未定义。remoteFamily:客户端是IPvX包返回异常处理。服务器端收到客户端发送来的待处理数据后,进入处理环节。如果在业务逻辑处理完成之前socket断开,则服务端返回给客户端时会直接响应。error事件并上报Error:Thissockethasbennendedbytheotherpart,所以在回报之前,服务器需要判断socket是否已经被销毁,如果没有被销毁,则返回数据包,如果已经断开连接,销毁它:varnet=require('net');varbiz=require('./biz');varserver=net.createServer(function(socket){socket.on('data',function(data){biz.do(data).then(function(){if(!socket.destroyed){socket.write(data.toString());}else{//做一些报告socket.destry();}}).catch(function(){!socket.destroyed&&socket.end('serverhandlererror');});}).on('end',function(){console.log('socketend')})。on('error',function(error){console.log('sock等错误',错误);});});server.listen(56200,function(){console.log('serverrunat',server.address());});server.on('error',function(err){throw呃;});限制客户端数据大小限制请求大小是服务安全不可或缺的一部分。服务端不能接受所有客户端发送的无限大小的数据,但是Size是第一个阈值varnet=require('net');varMAX_REQUEST_BYTES=2*1024*1024;//2Mvarserver=net.createServer(function(socket){socket.on('data',function(data){if(data.bytesRead>MAX_REQUEST_BYTES){socket.pause();socket.end('dataistoobig,forbidden');//做一些报告}}).on('end',function(){console.log('socketend')}).on('error',function(error){console.log('socketerror',error);});});server.listen(56200,function(){console.log('serverrunat',server.address());});server.on('错误',函数(错误){抛出错误;});