node拼接udp请求包

鬼子母
• 阅读 5806

node拼接udp请求包

标签: nodejs udp tcp buffer


复习一下基础知识

byte bit

1byte代表的是一个字节,是文件存储的最小单位。在基本文件单位中,我们有以下的等价关系。 1M = 1024 K,1k = 1024 byte。

1bit代表则是一个Binary digit(二进制数位)。说人话,就是1010101中的一个1或者0。

TCP/UDP协议中,比较广泛的定义是1 byte = 8 bit,这个定义不是严格的。换句话说,你可以选择不遵守。

TCP/UDP

在计算机网络的七层协议中,这两个是传输层的协议,我们常用的HTTP协议属于一种特殊的TCP连接。一般情况下,我们将TCP连接通过IP作为地址关联,通过握手的方式连接,所以TCP协议又被称为是TCP/IP协议。udp协议则是一种更为暴力的协议,一般没有握手的过程,我们经常会把它用在DNS的查询上面。

tcp和udp的区别
区别 udp tcp
连接性 面向非连接 面向连接
传输可靠性 不可靠 可靠
应用场景 少量数据 传输大量数据
速度

好了,我们先复习到这里。如果还有不知道的,请QQ你们的计算机网络老师。

node环境下的协议使用。

对于tcp/HTTP协议的场景,大家其实都是比较熟悉的,成熟的框架大家都是用的六六的,所以这里就不再赘述,下文将着重于表达UDP协议。

连接方式

嗯,我们先来看一下一个简单的udp的例子。


// server.js
const dgram = require('dgram');
const server = dgram.createSocket('udp4');

server.on('error', (err) => {
  console.log(`server error:\n${err.stack}`);
  server.close();
});

server.on('message', (msg, rinfo) => {
  console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});

server.on('listening', () => {
  var address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

server.bind(41234,()=>{
    console.log('server bind success');
});
// server listening 0.0.0.0:41234


//client.js
const dgram = require('dgram');
const message = Buffer.from('Some bytes');
const client = dgram.createSocket('udp4');
client.send(message, 41234, 'localhost', (err) => {
  client.close();
});

代码还是很简单的。使用到的库是dgram这个库是node自带的,直接require就ok,有关的事件如下:

  • error 当发生错误的时候会触发这个事件。

  • message 当收到了udp请求的时候将会被触发。

  • listening 当接口被绑定之后,如果绑定承购,开始监听的时候,将会触发该事件。

  • close 当udp请求被关闭的时候,将会触发该事件。

常用的方法函数,如下:

  • createSocket 创建实例,这里能够创建的类型是udp4/udp6,分别对应的是ipv4/ipv6

  • bind 绑定指定的接口

  • send 发出指定的message。这里有个坑,message的类型只支持 Buffer|String|Array

具体的函数介绍和使用说明,请参阅官方文档。对于一个简单udp协议,使用的时候,我们一般将会把监听和请求合并封装在一起,作为一个统一服务。

var dgram = require('dgram');
var server = dgram.createSocket('udp4')
var port = 0;
var targetPort = 123;
var targetIp = 10.10.10.10;//这里也可以支持用域名,它会自己做dns解析
function sendAndRecv(targetPort,targetIp,desPort,message,callback){
    server.bind(port,()=>{
        var _message = Buffer.from(message);
        server.send(_message,targetPort,targetIp,(err)={
            if(!err){
                server.on('message',(msg,info)=>{
                    console.log(`server got: ${msg.toString()} from ${info.address}:${info.port}`);
                    callback&&callback(message.toString());
                    //这里要注意哦,msg的类型是Buffer哦!
                })
            }
        })
    })
}

位操作

后端的同学使用的语言是c/c++对于他们来说,实现一个和协议一毛一样的东西是比较好理解的,毕竟,当年定义协议的人,也是写这个的嘛。但是,对于我们前端而言,我们能够依赖的就只有我们的node了。node的运行是基于v8的,所以,本质上来说,node并不具备有直接内存操作能力,所以,为了操作各种bit位,我们需要引入一个新的变量类型Buffer,这个类型是node独有的,在浏览器内核中,与之最接近的是ArrayBuffer,在用来处理音视频流的在WEBRTC中我们经常能用的到它。

Buffer对象的使用

js嘛,还是比较简单的。我们直接看代码吧。

//实例化
var buf = new Buffer();

//写
buf.write("XXXXX");


//读
buf.readInt8();

具体的类型说明和函数使用,请参考官方文档

我们这里着重说一下踩过的坑。在buffer对象中,使用的是byte记位。也就是说,对于如下:

var buf = new Buffer(1);// 1 byte == 8bit 可以写入 0x00 = 0000 0000 
buf.writeInt8(0x00);

//对于16进制的不同位数,可以参考如下函数:
//不同的长度,在写入的时候,要使用不同的函数,具体需要使用到的函数请参考,上文给出的官方文档。
function getBuffer(value, length) {
    var buffer = length && new Buffer(length);
    switch (length) {
        case 1:
            buffer.writeUInt8(value);
            return buffer;
        case 2:
            buffer.writeInt16BE(value);
            return buffer;
        case 4:
            buffer.writeFloatBE(value);
            return buffer;
        default:
            return new Buffer(value);
    }
}

这里顺带加一个函数,如何把十进制的ip string转换成整型数据的js实现。

function ip2Int(IP) {
    var REG = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
    var xH = "", result = REG.exec(IP);
    if (!result) return false;
    return (parseInt(result[1]) << 24
    | parseInt(result[2]) << 16
    | parseInt(result[3]) << 8
    | parseInt(result[4]));
}

ip2Int("10.10.10.10");//168430090
点赞
收藏
评论区
推荐文章
代码哈士奇 代码哈士奇
4年前
uni-app使用uniCloud时做类似于拦截器和请求结果再处理(类似于请求和响应拦截)
想要在使用uniCloud的使用拦截请求怎么办再次封装uniCloud.callFunction特别说明这里的token是我自己存储成token如果你使用了uniid官方的推荐是('uniidtoken')('uniidtokenexpired')存储了uniidtoken后请求会自动携带这里的res.result.code0是因为我的云
小嫌 小嫌
3年前
Node.js学习笔记
什么是Node.js文件?Node.js文件包含将在特定事件上执行的任务一个典型的事件是有人试图访问服务器上的端口Node.js文件必须在服务器上启动才能生效Node.js文件的扩展名为“.js”Node.js文件应当如何执行推荐使用各种类型的编译器生成一个空白的nodedemo.js文件,在文件中输入下面的内容:varhttprequi
Easter79 Easter79
3年前
sql:mysql:函数:TIMESTAMPDIFF函数实现TimeStamp字段相减,求得时间差
<divclass"htmledit\_views"id"content\_views"<p&nbsp;函数内指定是minute,则最终结果value值的单位是分钟,如果函数内指定为hours,则最终结果value值单位为小时。</p<preclass"has"name"code"<codeclass"hljssql"<
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
IM总结
发送消息UDP打洞,登录的时候HTTP。登录成功后,会有一个TCP连接来保持在线状态。这个TCP连接的远程端口一般是80,采用UDP方式登录的时候,端口是8000。如果采用UDP协议,通过服务器中转方式。UDP协议是不可靠协议,它只管发送,不管对方是否收到的。如果client使用UDP协议发送消息后,服务器收到该包,需要使用UDP协议发回一个
Stella981 Stella981
3年前
Javascript操作DOM常用API总结
        文本整理了javascript操作DOM的一些常用的api,根据其作用整理成为创建,修改,查询等多种类型的api,主要用于复习基础知识,加深对原生js的认识。基本概念        在讲解操作DOM的api之前,首先我们来复习一下一些基本概念,这些概念是掌握api的关键,必须理解它们。Node类型
Wesley13 Wesley13
3年前
C语言位运算
一、掩码运算1.什么是掩码?计算机中最小的单位是字节,一个字节代表8个二进制位。在实际的应用中许多信息并不需要使用一个字节来表示。例如表示当前系统运行是否正常,这种标志的取值只有0和1两种。因此使用是个完整的字节保存该标志就很浪费了。这些标志为是以位的形式存储的,因此当需要提取这些标志位的时候就需要使用掩码。掩码是人为生成的整数值,
Stella981 Stella981
3年前
Es6获取数据
$(function(){$.ajax({//请求方式type:"GET",//文件位置url:"js/data.json",//返回数据格式为json,也可以是其他格式如dataType:"json",//请求成功后要执行的函数,拼接htmlsuccess:function(res){var
Stella981 Stella981
3年前
Node.js 中使用 ECDSA 签名遇到的坑
文/Fenying最近有个朋友问我关于Node.js下使用ECDSA的问题,主要是使用Node.js的Crypto模块无法校验网络传输过来的签名结果。在踩坑无数后,终于搞清楚了原因。坑0x00:签名输出格式在排除了证书、消息不一致的可能之后,我开始对比使用Node.js签名的结果与网络传输过来的签
Stella981 Stella981
3年前
Linux stat函数和stat命令
stat函数和stat命令linux文件里的【inodeindexnode】解释:要理解inode必须了解磁盘和【目录项】,inode实际是连接【目录项】和磁盘的中间物质。图里的大圈代表硬件的磁盘,里面的小圈代表某个文件存储在磁盘上了。【inodeindexnode】的node(承载node信息的结
美凌格栋栋酱 美凌格栋栋酱
4个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(