nodejs 封包 訪問udp


nodejs 寫的 基於UDP 的client,將數據封裝成二進制,訪問udp server:

var rawCode = new Buffer("54ef43456565","hex");
console.log(rawCode)

//這個函數用來轉換大小端(swap endian between little and big)
function swapBytes(buffer) {
var l = buffer.length;
if (l & 0x01) {
throw new Error('Buffer length must be even');
}
for (var i = 0; i < l; i += 2) {
var a = buffer[i];
buffer[i] = buffer[i+1];
buffer[i+1] = a;
}
return buffer;
}


function cppString(str,len){

this.str = "";
if(str.length > len-1){
this.str = str.slice(0,len-1);
}else{
this.str = str;
}
this.str += "\0";

this.byteLen = len;
this.buffer = new Buffer(this.byteLen);
this.length = this.buffer.length;

this.process();
}

cppString.prototype.toString = function(){
return this.buffer.toString();
}

cppString.prototype.getLength = function(){
return this.buffer.length;
}

cppString.prototype.process = function(){
this.buffer.fill(0);
this.buffer.write(this.str);
/*for(var i=this.str.length;i < this.buffer.length;i++){
this.buffer[i] = 0x00;
}*/
//this.buffer = swapBytes(this.buffer);
//console.log(this.buffer)
}




function cppNum(num,intType){

this.num = num;

this.buffer = null;
this.value = null;
this.numArray = null;
this.byteLen = null
this.intType = intType;

switch(this.intType){
case "uint8":
this.numArray = new Uint8Array([num]);
this.byteLen = 1;
break;
case "uint16":
this.numArray = new Uint16Array([num]);
this.byteLen = 2;
break;
case "uint32":
this.numArray = new Uint32Array([num]);
this.byteLen = 4;
break;
case "int8":
this.numArray = new Int8Array([num]);
this.byteLen = 1;
break;
case "int16":
this.numArray = new Int16Array([num]);
this.byteLen = 2;
break;
case "int32":
this.numArray = new Int32Array([num]);
this.byteLen = 4;
break;
default:
break;
}


this.process();
}


cppNum.prototype.process = function(){

this.value = this.numArray[0];
this.buffer = new Buffer(this.byteLen);
this.buffer.fill(0);//clear all the buffer

switch(this.intType){
case "uint8"://uint8
this.buffer.writeUInt8(this.value,0);//little endian (按小端對齊)
break;
case "uint16"://uint16
this.buffer.writeUInt16LE(this.value,0);//little endian (按小端對齊)
break;
case "uint32"://uint32
this.buffer.writeUInt32LE(this.value,0);//little endian (按小端對齊)
break;
case "int8"://int8
this.buffer.writeInt8(this.value,0);//little endian (按小端對齊)
break;
case "int16"://int16
this.buffer.writeInt16LE(this.value,0);//little endian (按小端對齊)
break;
case "int32"://int32
this.buffer.writeInt32LE(this.value,0);//little endian (按小端對齊)
break;
default:break;
}

//console.log(this.buffer);
//var rawValue = this.value.toString();

//for(var i=0;i < this.byteLen;i++){
//this.buffer[i] = rawValue >> (8*i);
//}

//this.buffer = swapBytes(this.buffer);
}



function pack(listObj){

var listBuffer = new Array();
this.length =0;
for(var i=0;i < listObj.length;i++){
listBuffer.push(listObj[i].buffer);
this.length += listObj[i].byteLen;
}
this.buffer = Buffer.concat(listBuffer);
}

console.log("--------start send data by udp protocal----------------");

var dgram = require("dgram");
var socket = dgram.createSocket("udp4");
socket.bind(function () {
socket.setBroadcast(true);
});

var name = new cppString("zhengjinwei zhengjinwei zhengjinwei",20);//如果長度超過20,自動截取前19個,最后一個是"\0"
var sex = new cppString("male",10);
var age = new cppNum(2147483647,"int32");
var data = new cppString("this is a demo for using js to pack net work package to binary type",100);

var msg = new pack([name,sex,data,age]);

socket.send(msg.buffer,0, msg.length, 21210, '127.0.0.1', function(err, bytes) {
socket.close();
});




下面是c++寫的基於 UDP 的 server:

// ConsoleApplication1.cpp : 定義控制台應用程序的入口點。
//

#include "stdafx.h"
#include <Winsock2.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")

#pragma pack(push)
#pragma pack(1)

//注意:要按一字節對齊,否者數據長度有錯
struct SMsg
{
char name[20];
char sex[10];
char strMsg[100];
int age;
};


void main()
{

int value =sizeof(SMsg);

printf("%d",value);

WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested=MAKEWORD(1,1);

err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{

return;
}

if (LOBYTE(wsaData.wVersion)!=1 ||
HIBYTE(wsaData.wVersion)!=1)
{
WSACleanup();
return;
}

SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(21210);

bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);

while(true){
char recvBuf[400];

recvfrom(sockSrv,recvBuf,400,0,(SOCKADDR*)&addrClient,&len);

SMsg *pmsg = (SMsg*)(recvBuf);

printf("name=%s,age=%d,sex=%s,data=%s\n",pmsg->name,pmsg->age,pmsg->sex,pmsg->strMsg);
}

closesocket(sockSrv);
WSACleanup();
}

#pragma pack(pop)

 

 



上面那個node寫的client不夠好,再次進行封裝,如下:

function cppString(str,len){

this.str = "";
if(str.length > len-1){
this.str = str.slice(0,len-1);
}else{
this.str = str;
}
this.str += "\0";

this.byteLen = len;
this.buffer = new Buffer(this.byteLen);
this.length = this.buffer.length;

this.process();
}

cppString.prototype.toString = function(){
return this.buffer.toString();
}

cppString.prototype.getLength = function(){
return this.buffer.length;
}

cppString.prototype.process = function(){
this.buffer.fill(0);
this.buffer.write(this.str);
/*for(var i=this.str.length;i < this.buffer.length;i++){
this.buffer[i] = 0x00;
}*/
}




function cppNum(num,intType){

this.num = num;

this.buffer = null;
this.value = null;
this.numArray = null;
this.byteLen = null
this.intType = intType;

switch(this.intType){
case "uint8":
this.numArray = new Uint8Array([num]);
this.byteLen = 1;
break;
case "uint16":
this.numArray = new Uint16Array([num]);
this.byteLen = 2;
break;
case "uint32":
this.numArray = new Uint32Array([num]);
this.byteLen = 4;
break;
case "int8":
this.numArray = new Int8Array([num]);
this.byteLen = 1;
break;
case "int16":
this.numArray = new Int16Array([num]);
this.byteLen = 2;
break;
case "int32":
this.numArray = new Int32Array([num]);
this.byteLen = 4;
break;
default:
break;
}
this.process();
}


cppNum.prototype.process = function(){

this.value = this.numArray[0];
this.buffer = new Buffer(this.byteLen);
this.buffer.fill(0);//clear all the buffer

switch(this.intType){
case "uint8"://uint8
this.buffer.writeUInt8(this.value,0);//little endian (按小端對齊)
break;
case "uint16"://uint16
this.buffer.writeUInt16LE(this.value,0);//little endian (按小端對齊)
break;
case "uint32"://uint32
this.buffer.writeUInt32LE(this.value,0);//little endian (按小端對齊)
break;
case "int8"://int8
this.buffer.writeInt8(this.value,0);//little endian (按小端對齊)
break;
case "int16"://int16
this.buffer.writeInt16LE(this.value,0);//little endian (按小端對齊)
break;
case "int32"://int32
this.buffer.writeInt32LE(this.value,0);//little endian (按小端對齊)
break;
default:break;
}
}





function msg(host,port){
this.listBuffer = new Array();;
this.length = 0;

this.port = port;
this.host = host;
}

msg.prototype.push_uint8 = function(value){
var uint8Value = new cppNum(value,"uint8");
this.listBuffer.push(uint8Value.buffer);
this.length += uint8Value.byteLen;
}
msg.prototype.push_int8 = function(value){
var int8Value = new cppNum(value,"int8");
this.listBuffer.push(int8Value.buffer);
this.length += int8Value.byteLen;
}
msg.prototype.push_uint16 = function(value){
var uint16Value = new cppNum(value,"uint16");
this.listBuffer.push(uint16Value.buffer);
this.length += uint16Value.byteLen;
}
msg.prototype.push_int16 = function(value){
var int16Value = new cppNum(value,"int16");
this.listBuffer.push(int16Value.buffer);
this.length += int16Value.byteLen;
}
msg.prototype.push_uint32 = function(value){
var uint32Value = new cppNum(value,"uint32");
this.listBuffer.push(uint32Value.buffer);
this.length += uint32Value.byteLen;
}
msg.prototype.push_int32 = function(value){
var int32Value = new cppNum(value,"int32");
this.listBuffer.push(int32Value.buffer);
this.length += int32Value.byteLen;
}

msg.prototype.push_string = function(strValue,len){
var strValue = new cppString(strValue,len);
this.listBuffer.push(strValue.buffer);
this.length += strValue.byteLen;
}

msg.prototype.push_char = function(strChar){
var strValue = new cppString(strValue,2);
this.listBuffer.push(strValue.buffer);
this.length += strValue.byteLen;
}
msg.prototype.send = function(){
if(this.listBuffer.length > 0){
var dgram = require("dgram");
var socket = dgram.createSocket("udp4");
socket.bind(function () {
socket.setBroadcast(true);
});
var buffer = Buffer.concat(this.listBuffer);
socket.send(buffer,0, this.length, this.port,this.host, function(err, bytes) {
socket.close();
});
}
}


console.log("--------start send data by udp protocal----------------");

var messgae = new msg("127.0.0.1",21210);

messgae.push_string("zhengjinwei",20);
messgae.push_string("male",10);
messgae.push_string("my name is zhengjinwei",100);
messgae.push_int32(212121212);

messgae.send();



參考網站:http://stackoverflow.com/questions/14730980/nodejs-write-64bit-unsigned-integer-to-buffer



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com