标签: nodejs udp tcp bufferjavascript
1byte表明的是一个字节,是
文件存储
的最小单位。在基本文件单位中,咱们有如下的等价关系。 1M = 1024 K,1k = 1024 byte。html1bit表明则是一个Binary digit(二进制数位)。说人话,就是1010101中的一个1或者0。前端
在TCP/UDP协议
中,比较普遍的定义是1 byte = 8 bit,这个定义不是严格的。换句话说,你能够选择不遵照。java
在计算机网络的七层协议中,这两个是传输层的协议,咱们经常使用的HTTP协议属于一种特殊的TCP链接。通常状况下,咱们将TCP链接经过IP做为地址关联,经过握手的方式链接,因此TCP协议又被称为是TCP/IP协议。udp协议则是一种更为暴力的协议,通常没有握手的过程,咱们常常会把它用在DNS的查询上面。node
区别 | udp | tcp |
---|---|---|
链接性 | 面向非链接 | 面向链接 |
传输可靠性 | 不可靠 | 可靠 |
应用场景 | 少许数据 | 传输大量数据 |
速度 | 快 | 慢 |
好了,咱们先复习到这里。若是还有不知道的,请QQ大家的计算机网络老师。c++
对于tcp/HTTP协议的场景,你们其实都是比较熟悉的,成熟的框架你们都是用的六六的,因此这里就再也不赘述,下文将着重于表达UDP协议。git
嗯,咱们先来看一下一个简单的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,有关的事件以下:api
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中咱们常常能用的到它。
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