Node.js之网络通讯模块实现浅析

前言

想必我们在用Node.js用的最多的应该是创建http服务,所以对于每个Web开发工程师而言,Node.js的网络相关模块学习是必不可少。

Node.js的网络模块架构

在Node.js的模块里面,与网络相关的模块有Net、DNS、HTTP、TLS/SSL、HTTPS、UDP/Datagram,除此之外,还有v8底层相关的网络模块有tcp_wrap.ccudp_wrap.ccpipe_wrap.ccstream_wrap.cc等等,在Javascript层以及C++层之间通过process.binding进行桥接相互通信。

Net模块

Net模块提供了一些用于底层的网络通信接口,包括创建服务器以及客户端,其中HTTP模块也是基于Net模型的上层封装,在Net模块里面主要提供net.Server以及net.Socket

创建TCP服务端

创建一个TCP服务器,可以通过使用构造函数new net.Server或者使用工厂方法net.createServer,这两个方法都会返回一个net.Server类,可接收两个可选参数。

var net = require('net');

var server = net.createServer(function(socket){

  socket
    .on('data',function(data){
      console.log('socket data',data.toString());
      socket.write( data.toString() );
    })
    .on('end',function(){
      console.log('socket end')
    })
    .on('error',function(error){
      console.log('socket error',error);
    });
});

server.listen(56200,function(){
  console.log('server run at ',server.address());
});

server.on('error',function(err){
  throw err;
});
// 执行后:server run at { address: '::', family: 'IPv6', port: 56200 }

在listen监听的时候没有指定端口的话会自动随意监听一个端口,创建完成一个TCP服务器后,使用tenlent 0.0.0.0 56200,链接后可与服务器进行数据通信。通过createServer实例化一个服务后,服务会去监听客户端请求,与客户端建立了链接之后会在回调里面抛出建链的net.Socket对象。

创建TCP客户端

创建一个TCP客户端链接可以使用构造函数new net.Socket或者其工厂方法net.createConnection,创建成功后都会返回一个net.Socket实例。

var net = require('net');

var client = net.createConnection({port:56200,host:'localhost'});

client.on('connect',function(){
  console.log('client connect');
});

client.on('data',function(data){
  console.log('client data',toString());
});

client.on('error',function(error){
  throw error;
});

client.on('close',function(){
  console.log('client close');
});

Socket

socket是啥这里就不做详细的阐述了,下面主要了解下net.Socket这个构造体主要有提供一些什么方法、监听事件的使用。

相关事件

  1. connect : 当客户端与服务端成功建立链接之后触发,如果链接不上服务器直接抛出error事件错误然后退出node进程。
  2. data : 当客户端收到服务器传送过来的数据或者是客户端传送给服务器的数据的时候触发回调。
  3. end : 当另外一侧发送FIN包断开的时候触发,默认情况下面 (allowHalfOpen == false)socket会自我销毁(如果写入待处理队列里面还没正式响应回包),但是我们可以设置allowHalfOpen参数为true,这样可以继续往该socket里面写数据,但是我们需要自己去调用 end 方法去消耗这个socket,不然可能会造成句柄泄漏。
  4. close : 链接断开的时候触发,但是如果在传输的过程中有错误的话这里会在回调函数里面抛出 error。
  5. timeout : 当socket超时空闲的时候触发,如果要在队列里面销毁需要手动去调close方法。
  6. lookup : 域名解析完成的时候触发。
  7. drain : 写完缓存的时候触发,可使用在上传大小限制中。

相关方法

  1. write() : 服务端给客户端发送数据或者是客户端给服务端发送数据。
  2. address() : 获取服务绑定的socket的IP地址,返回对象有三个属性,分别为端口、host以
  3. 及IPvX版本。
  4. end() : 半关闭socket,会发送一个FIN包,服务器仍然可能发送一些数据,也可以这样调用socket.end(data,encoding)。
  5. pause() : 暂停读取数据,可以用作对数据上传限制。
  6. resume() : 继续数据读取。
  7. setEncoding() : 设置数据流的获取格式。
  8. setKeepAlive() : 允许/禁止keep-alive功能。
  9. setNoDelay() : 禁止Nagele算法,TCP链接默认使用Nagle算法,它们在发送之前数据会被缓存。这是为true的话在每次socket.write()的时候会立即发送数据,默认为true。
  10. setTimeout() : 当一个空闲的socket在多少秒后不活跃会被接受到timeout事件,但是该socket不会停止销毁,需要手动调用end()或者destroy()。表示禁止空闲超时。

相关属性

  1. bufferSize : 当前缓存的等待被发送的字符串的数量。
  2. bytesRead : 收到的字节的数量。
  3. bytesWritten : 发送的字节的数量
  4. destroyed : 标识链接是否已经被破坏,一旦被破环,就不用使用该链接来传输数据。
  5. localAddress : 远程客户端链接本地地址的host。如果我们监听服务的host是0.0.0.0,而客户端链接的是'192.168.1.1',最后的值是后者。
  6. localPort : 本地的端口。
  7. remoteAddress : 客户端IP,如果socket已经是destryed的话,该值为undefined
  8. remoteFamily : 客户端是IPvX

回包异常处理

服务器从客户端接受到需要处理的数据后进入处理环节,再业务逻辑处理完成之前如果socket以外断开的话,待服务器再给客户端回报的时候会直接响应error事件并报错Error : This socket has benn ended by the other part,所以在回报之前服务端需要先判断该socket是否被销毁,如果没有被销毁则回包,如果已经断开则销毁:

var net = require('net');
var biz = require('./biz');
var server = net.createServer(function(socket){

  socket
    .on('data',function(data){
      biz.do(data)
        .then(function(){
          if( !socket.destroyed ) {
            socket.write( data.toString() );
          } else {
            // do some report
            socket.destry();
          }
        })
        .catch(function(){
          !socket.destroyed && socket.end('server handler error');
        });

    })
    .on('end',function(){
      console.log('socket end')
    })
    .on('error',function(error){
      console.log('socket error',error);
    });
});

server.listen(56200,function(){
  console.log('server run at ',server.address());
});

server.on('error',function(err){
  throw err;
});

限制客户端数据大小

对请求大小限制是服务安全里面比不可少的一个环节,服务端不能无限大小的去接受客户端发送过来的所有数据,而限制大小就是第一道门槛。

var net = require('net');
var MAX_REQUEST_BYTES = 2 * 1024 * 1024; // 2M
var server = net.createServer(function(socket){

  socket
    .on('data',function(data){

      if(data.bytesRead > MAX_REQUEST_BYTES) {
        socket.pause();
        socket.end('data is too big, forbidden');
        // do some report
      }
    })
    .on('end',function(){
      console.log('socket end')
    })
    .on('error',function(error){
      console.log('socket error',error);
    });
});

server.listen(56200,function(){
  console.log('server run at ',server.address());
});

server.on('error',function(err){
  throw err;
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于html5和nodejs相结合实现websocket即使通讯

    最近都在学习HTML5,做canvas游戏之类的,发现HTML5中除了canvas这个强大的工具外,还有WebSocket也很值得注意.可以用来做双屏互动游戏,何为双屏互动游戏?就是通过移动端设备来控制PC端网页游戏.这样的话就要用到实时通讯了,而WebSocket无疑是最合适的.WebSocket相较于HTTP来说,有很多的优点,主要表现在WebSocket只建立一个TCP连接,可以主动推送数据到客户端,而且还有更轻量级的协议头,减少数据传送量.所以WebSocket暂时来说是实时通讯的最佳协

  • Nodejs+Socket.io实现通讯实例代码

    目录结构 D:. │ package.json │ server.js │ └─public index.html socket.io.js 需要的条件 socket.io.js 供前端界面初始化io socket.io 供NodeJs端提供socket方法 socket.io.js存在于socket.io-client socket.io存在于socket.io 演示的功能 客户端发送消息给服务端 后端触发事件告知客户端 客户端离开触发服务端事件 服务端 server.js var expre

  • 学习 NodeJS 第八天:Socket 通讯实例

    前言 一般来讲,HTTP 是基于文本的"单向"通讯机制.这里所谓的"单向",乃相对于"双向"而言,因为 HTTP 服务器只需根据请求返还恰当的 HTML 给客户端即可,不涉及客户端向服务端的通讯.这种单向的机制比较简单,对网络质量要求也不高.而更多的场景则是需要可靠.稳定的端到端连接.一般这种服务是实时的.有态的而且是长连接,长连接则暗示两段须达致相向通讯的能力,也就说是服务端客户端两者间能够实时地相互间通信.毫无疑问,能够实时通信的服务器正是我

  • AngularJS + Node.js + MongoDB开发的基于高德地图位置的通讯录

    一.闲扯 有一天班长说了,同学们希望我开发一个可以共享位置的通讯录,于是自己简单设计了下功能.包括用户角色.发表微博.共享位置等等.这次也是有点私心的,为了锻炼最近看的angularjs,于是果断选择Node.js + MongoDB + angular.js的方案.当然,开发Node.js的体会越来越深刻.记得,去年leader告诉我说尽量让node的每一个服务只支撑一个业务功能,这样才能更方便的维护.当时特别想把一个Node服务做的特别强大.现在看来leader的做法是对的,我更加倾向于把n

  • 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等等,在Javascript层以及C++层之间通过proc

  • Node.js的基本知识简单汇总

    Node.js从2009年诞生至今,已经发展了两年有余,其成长的速度有目共睹.从在github的访问量超过Rails,到去年底Node.jsS创始人Ryan Dalh加盟Joyent获得企业资助,再到今年发布Windows移植版本,Node.js的前景获得了技术社区的肯定.InfoQ一直在关注Node.js的发展,在今年的两次Qcon大会(北京站和杭州站)都有专门的讲座.为了更好地促进Node.js在国内的技术推广,我们决定开设"深入浅出Node.js"专栏,邀请来自Node.js领域

  • 基于node.js的快速开发透明代理

    但是最近服务器端js的火爆确实因为node.js项目.在velocity china 2010大会Douglas Crockford(Yahoo!)也有一个topic<卷土重来:服务器端JavaScript>提到node.js.关于node.js的详细资料请google. node.js的非常大的一个特点就是事件驱动,在开发服务器端服务的时候显得非常方便.昨晚在新浪的@timYang也提到了node.js,估计新浪微博也注意到了它的优点.同时,淘宝最近也表示对node.js有相当的兴趣.参见:

  • 我的Node.js学习之路(三)--node.js作用、回调、同步和异步代码 以及事件循环

    一,node.js的作用, I/O的意义,(I/O是输入/输出的简写,如:键盘敲入文本,输入,屏幕上看到文本显示输出.鼠标移动,在屏幕上看到鼠标的移动.终端的输入,和看到的输出.等等)   node.js想解决的问题,(处理输入,输入,高并发 .如 在线游戏中可能会有上百万个游戏者,则有上百万的输入等等)(node.js适合的范畴:当应用程序需要在网络上发送和接收数据时Node.js最为适合.这可能是第三方的API,联网设备或者浏览器与服务器之间的实时通信)   并发的意义,(并发这个术语描述的

  • Node.js中的缓冲与流模块详细介绍

    缓冲(buffer)模块 js起初就是为浏览器而设计的,所以能很好的处理unicode编码的字符串,但不能很好的处理二进制数据.这是Node.js的一个问题,因为Node.js旨在网络上发送和接收经常是以二进制格式传输的数据.比如: - 通过TCP连接发送和接收数据:  - 从图像或者压缩文件读取二进制数据:  - 从文件系统读写数据:  - 处理来自网络的二进制数据流 而Buffer模块为Node.js带来了一种存储原始数据的方法,于是可以再js的上下文中使用二进制数据.每当需要在Node.j

  • 从零学习node.js之简易的网络爬虫(四)

    前言 之前已经介绍了node.js的一些基本知识,下面这篇文章我们的目标是学习完本节课程后,能进行网页简单的分析与抓取,对抓取到的信息进行输出和文本保存. 爬虫的思路很简单: 确定要抓取的URL: 对URL进行抓取,获取网页内容: 对内容进行分析并存储: 重复第1步 在这节里做爬虫,我们使用到了两个重要的模块: request : 对http进行封装,提供更多.更方便的接口供我们使用,request进行的是异步请求.更多信息可以去这篇文章上进行查看 cheerio : 类似于jQuery,可以使

  • 使用Node.js配合Nginx实现高负载网络

    在搭建高吞吐量web应用这个议题上,NginX和Node.js可谓是天生一对.他们都是基于事件驱动模型而设计,可以轻易突破Apache等传统web服务器的C10K瓶颈.预设的配置已经可以获得很高的并发,不过,要是大家想在廉价硬件上做到每秒数千以上的请求,还是有一些工作要做的. 这篇文章假定读者们使用NginX的HttpProxyModule来为上游的node.js服务器充当反向代理.我们将介绍Ubuntu 10.04以上系统sysctl的调优,以及node.js应用与NginX的调优.当然,如果

  • node.js通过axios实现网络请求的方法

    1.使用Npm 下载axios npm install --save axios var update_url = axios.create({ baseURL:'debug url' }); update_url.get('/debug url').then(function (response){ //response 就是请求url 返回的内容 } 上述的方法请求文件时候,body的默认格式不是form-data.因此我们需要请求的数据格式为form-data的时候,需要使用下面的库 re

  • 浅析Node.js非对称加密方法

    前言 刚回答了SegmentFault上一个兄弟提的问题<非对称解密出错>.这个属于Node.js在安全上的应用,遇到同样问题的人应该不少,基于回答的问题,这里简单总结下. 非对称加密的理论知识,可以参考笔者前面的文章<NODEJS进阶:CRYPTO模块之理论篇>. 完整的代码可以在 <Nodejs学习笔记> 找到,也欢迎大家关注 程序猿小卡的GitHub. 加密.解密方法 在Node.js中,负责安全的模块是crypto.非对称加密中,公钥加密,私钥解密,加解密对应的

  • 深入浅析Node.js 事件循环、定时器和process.nextTick()

    什么是事件循环 尽管JavaScript是单线程的,但通过尽可能将操作放到系统内核执行,事件循环允许Node.js执行非阻塞I/O操作. 由于现代大多数内核都是多线程的,因此它们可以处理在后台执行的多个操作. 当其中一个操作完成时,内核会告诉Node.js,以便可以将相应的回调添加到 轮询队列 中以最终执行. 我们将在本主题后面进一步详细解释. 事件循环解释 当Node.js启动时,它初始化事件循环,处理提供的输入脚本(或放入 REPL ,本文档未涉及),这可能会进行异步API调用,调度计时器或

随机推荐