week 16

环境及功能设定

Client:生成CoAP消息,用WebSocket发送至Proxy
Proxy: 提取CoAP消息,转发至Server,并将响应回发至Client
Server:接受CoAP消息,解析、再重新封装后,回复

具体使用的模块:

Client:
用`coap-packet`模块的`generate`方法生成CoAP消息;
用`nodejs-websocket`模块的`sendBinary()`方法发消息;
用`nodejs-websocket`模块的`on('binary', callback)`事件监听接收响应。

Proxy:
用`nodejs-websocket`模块的`on('binary', callback)`事件监听接收WebSocket消息;
用`UDP dgram`模块(Node.js自带)的`send()`方法,把作为payload的CoAP消息转发给Server;
用`UDP dgram`模块的`on('message', callback)`事件监听接收响应;
用`nodejs-websocket`模块的`sendBinary()`方法,把响应回发至Client。

Server:
用`UDP dgram`模块的`on('message', callback)`事件监听接收响应;
用`UDP dgram`模块(Node.js自带)的`send()`方法,把作为payload的CoAP消息转发给Server。

Q. proxy怎么正确接受client通过sendBinary()发送来的数据?

`conn.on('binary', ballback)`怎么用?
test.js内容有无借鉴?

A. 借鉴websocket模块中test.js的getServer()函数
function getServer(ontext, onbinary) { testConn.removeAllListeners(); if (ontext) testConn.on('text', ontext); if (onbinary) testConn.on('binary', onbinary); }
和调用了它的测试片段。
“`
it(‘should send binary data’, function(done){
var client = getClient(),
buffer = getBuffer(17);

    Client.sendBinary(buffer);

    getServer(null, function (inStream) {
        inStream.on('readable', function () {
            compareBuffers(inStream.read(), buffer)
        });
        inStream.on('end', done);
    });
})
```

Node.js用Buffer类处理二进制数据

JS善于处理字符串,但不善于处理二进制数据。JS没有字节类型,也没有结构化类型、字节数组类型,只有数值类型和字符串类型。
Node.js需要处理像TCP流或文件流时,必须要处理二进制数据。Node.js定义了一个Buffer类来解决这个问题。缓冲区的长度以字节为计量单位,并且可以随机地设置和获取缓冲区中的数据。

类:BUFFER

  • 构造方法
    1.new Buffer(size):分配一个新的buffer大小是size的8位字节
    2.new Buffer(array):分配一个新的buffer使用一个8位字节array数组
    3.new Buffer(str, [encoding]):encoding String类型-使用什么编码方式,参数可选
  • 类方法
    1.Buffer.isEncoding(encoding):如果给定的编码encoding是有效的,返回 true,否则返回false
    2.Buffer.isBuffer(obj):测试这个obj是否是一个Buffer. 返回Boolean
    3.Buffer.concat(list, [totalLength]):list {Array}数组类型,Buffer数组,用于被连接。totalLength {Number}类型 上述Buffer数组的所有Buffer的总大小
  • 写入缓冲区
    var buffer = new Buffer(8);//创建一个分配了8个字节内存的缓冲区
    console.log(buffer.write(‘a’,’utf8′));//输出1
    这会将字符”a”写入缓冲区,node返回经过编码以后写入缓冲区的字节数量,这里的字母a的utf-8编码占用1个字节。
  • 复制缓冲区
    Node.js提供了一个将Buffer对象整体内容复制到另一个Buffer对象中的方法。我们只能在已经存在的Buffer对象之间复制,所以必须创建它们。
    buffer.copy(bufferToCopyTo)
    其中,bufferToCopyTo是要复制的目标Buffer对象。如下示例:
var buffer1 = new Buffer(8);
buffer1.write('nice to meet u','utf8');
var buffer2 = new Buffer(8);
buffer1.copy(buffer2);
console.log(buffer2.toString());//nice to meet u

Node.js的流模块

Node.js中很多对象都实现了流,一个例子是TCP套接字,可以在其上进行读写操作;另一个例子是文件,可以对其进行顺序地追加和读取。按流的可操作性有可读流和可写流之分。

在类UNIX系统Stream是通过”|”实现对流的操作,node.js中对流的操作是通过.pipe()方法。

可读流操作

在创建或者获取一个可读流(如:读取一个文件后、收到一个client端HTTPt responses后)之后,可以对其进行一些控制和操作。例如:可以通过暂停和恢复来控制数据的流动、可以在收到数据时得到data通知、可以在流终止时关闭传输。

  1. ‘data’ 事件等待数据传输
var readable = getReadableStreamSomehow();   //getReadableStreamSomehow()是一个获得可读流的方法
readable.on('data', function(chunk) {
  //本次得到的数据块chunk
  console.log('got %d bytes of data', chunk.length);
});
  1. 流的暂停与恢复
    可读流就像一个阀门,可以通暂停来数据流动,可以通resume()方法恢复传输。示例如下:
var readable = getReadableStreamSomehow();
readable.on('data', function(chunk) {
  console.log('got %d bytes of data', chunk.length);
  readable.pause(); //暂停
  console.log('接下来的1秒数据传输将会暂停');
  setTimeout(function() {
    console.log('数据传输恢复');
    readable.resume();   //恢复
  }, 1000);
});
  1. 流传输结束

流传输结果后会收到”end”事件,通过监听”end”事件可以进行一些流传输结束后的处理。示例如下:

var readable = getReadableStreamSomehow();   //getReadableStreamSomehow()是一个获得可读流的方法

readable.on('data', function(chunk) {
  //本次得到的数据块chunk
  console.log('got %d bytes of data', chunk.length);
});

readable.on('end', function() {
  console.log('数据传输结束');
});

可写流操作

  1. 将数据写入可写流
    向流写入数据时,可以传送缓冲区Buffer数据或字符串。写入时,可设置第二个可选参数设置数据编码。示例如下:
var file = fs.createWriteStream('example.txt');
file.write('itbilu.com');
//写入数据时,可以设置编码格式
file.write('aXRiaWx1LmNvbQ==', 'base64');
//写缓冲区Buffer数据
var buf = new Buffer('itbilu.com');
file.write(buf);
  1. 可写流的完成与清空
    向流写入数据时,你会知道缓冲区数据是否被立即刷新,如果没有被刷新数据会被存储到内存中。在流成功刷新挂起的缓冲区时,stream会发送“drain”事件。写入完成后会发送“finish”事件。示例如下:
var writer = fs.createWriteStream('example.txt');
//假设这是一个可能会被挂起的缓冲区
var buf = new Buffer('itbilu.com');
writer.write(buf);

//刷新挂起的缓冲区时可写流缓冲区被清空,发送drain事件
writer.on('drain', fuction(){
   //对挂起事件的处理
})

//写入完成或调用end()方法后,将会发送finish事件
writer.on('finish', function() {
  console.error('所有数据已经写入完成.');
});

总结:Buffer是数据缓冲区对象,是二制数据在内存中的表现形式。Buffer中的数据可以按stream的形式传递到其它对象中。

wireshark对协议的识别

抓包遇到一个问题:有的包不被识别为COAP,只能显示UDP

《TCP/IP详解》中关于协议的分用:
1. 链路层:以太网首部中有不同帧类型用于表示以太网中帧内的数据;
2. IP数据包的首部:也有专门的8位协议类型,用于表示IP包中的上层协议类型(TCP是6,UDP是17);
3. 传输层的两个常用协议TCP和UDP首部中,并没有协议类型的字段,TCP和UDP包内的应用程协议的类型依靠的是TCP和UDP包首部的端口号来进行区分。对于一些常用的应用层协议IETF都规定了相应的熟知端口号。CoAP是5683。
《week 16》

wireshark可以针对非熟知端口的已知应用层协议设置相应的解码方式。具体的方法是:选中无法识别的报文->右键单击->Decode As->选择相应的应用层协议。
《week 16》

参考资料

  1. nodeJS-使用buffer类处理二进制数据
  2. Node.js Stream读写数据流
  3. wireshark对协议的识别
    原文作者:SmartJuneThx
    原文地址: https://segmentfault.com/a/1190000002991072
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞