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