node拼接udp請求包

node拼接udp請求包

標籤: nodejs udp tcp bufferjavascript


複習一下基礎知識

byte bit

1byte表明的是一個字節,是文件存儲的最小單位。在基本文件單位中,咱們有如下的等價關係。 1M = 1024 K,1k = 1024 byte。html

1bit表明則是一個Binary digit(二進制數位)。說人話,就是1010101中的一個1或者0。前端

TCP/UDP協議中,比較普遍的定義是1 byte = 8 bit,這個定義不是嚴格的。換句話說,你能夠選擇不遵照。java

TCP/UDP

在計算機網絡的七層協議中,這兩個是傳輸層的協議,咱們經常使用的HTTP協議屬於一種特殊的TCP鏈接。通常狀況下,咱們將TCP鏈接經過IP做爲地址關聯,經過握手的方式鏈接,因此TCP協議又被稱爲是TCP/IP協議。udp協議則是一種更爲暴力的協議,通常沒有握手的過程,咱們常常會把它用在DNS的查詢上面。node

tcp和udp的區別

區別 udp tcp
鏈接性 面向非鏈接 面向鏈接
傳輸可靠性 不可靠 可靠
應用場景 少許數據 傳輸大量數據
速度

好了,咱們先複習到這裏。若是還有不知道的,請QQ大家的計算機網絡老師。c++

node環境下的協議使用。

對於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中咱們常常能用的到它。

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
相關文章
相關標籤/搜索