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
#include
#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