=================================
=================================
=================================
출처ㅣ https://www.npmjs.com/package/cpp-struct-js
cpp-struct-js
The intention of this module is to interace node.js with an Arduino software I am writing. For this I need to read binary structures that are generated by C++ code running on an Arduino system.
Supported types:
- uint8,16,32
- int8,16,32
- float
- strings
Only one dimensional arrays are supported. It might be possible to extend the code to support this, but I don't see a need for this right now.
Pointers are not supported, but that wouldn't make sense anyway since serialization can't deal with native memory adresses.
Example
Reference
Class: struct (var struct = require('cpp-struct'))
Constructor signature: name, schema, [count, [bytes]]
- name: Internal name that's used when exporting and referencing other structs.
- schema: Interleaved array where even elements are variable name identifiers and odd elements are struct instances
- count (optional): If the type is supposed to be an array, this is the number of elements in the array
- bytes (optional): Size of a single element in bytes (total size = count * bytes)
Note: count and bytes arguments are used usually only internally - you don't have to worry about these if you don't intend to add new native types next to the currently implemented ones such as int/uint/float/double - say you'd want a int24, you'll need to care about these arguments.
Instance member: struct.setEncoder
Function signature: func
- func (buffer,pos,data,opt): Function that's called instead of the default encoder -- buffer: Buffer object to write to -- pos: position to write to -- data: the data value to be written (can be undefined) -- opt: optional options object that specifies encoding details (such as endianess)
Instance member: struct.setDecoder
추가 설명 .. decode에 대해서
//여기 모듈 "cpp-struct-js"에서 "decode(...)"함수의 설명이 없어서 따로 추가 설명한다.
//ES6 이상 모듈 방식으로 import, export 사용 아래와같이 node.js[npm] 에서
//(cpp-struct-js)을 인스톨해주고 아래와 같이 코드에 import 로 추가해준다.
import STRUCTCPP from "cpp-struct-js"; //es6 이상 버전에서 모듈화 import
var structT= new STRUCTCPP("structT", ["test1", STRUCTCPP.char(12),"test2", STRUCTCPP.uint32_t(),]);var structT2= new STRUCTCPP ("structT2", ["test3", STRUCTCPP .char(12),"test4", STRUCTCPP .uint32_t(),"test5", STRUCTCPP .uint32_t(),"info", STRUCTCPP.type(structT, 3), //이거는 info[3] 배열과 같은 뜻이라 보면 된다.]);//----------------------------------------------------------------------// encode 할때.var buffer = new Buffer(structT2.size());structT2.encode(buffer, 0, {test3: "Testing!!!",test4: 25,info:[{test1:"Hello"}, //배열 info[0]{test2: 6}, //배열 info[1]{test1:"good", test2: 2}, //배열 info[2]]},{endian: "LE"});//----------------------------------------------------------------------// decode 할때.var decodeDat = structT2.decode(buffer , 0, {endian:"LE"}); //위의 encode 할때 아까 변수값 "buffer"
var test3Dat = decodeDat.test3; //값: Testing!!!
var test4Dat = decodeDat.test4; //값: 25
var infoDat = decodeDat.info; //값: structT2->info
var infoDatTest0_1 = infoDat[0].test1; //값: "Hello"
var infoDatTest0_2 = infoDat[0].test2; //값: null
var infoDatTest1_1 = infoDat[1].test1; //값: null
var infoDatTest1_2 = infoDat[1].test2; //값: 6
var infoDatTest2_1 = infoDat[2].test1; //값: "good"
var infoDatTest2_2 = infoDat[2].test2; //값: 2
//ES6 이상 모듈 import, export 사용 아래와같이 node.js[npm]
//에서(cpp-struct-js, iconv, node-buffertrim)을 인스톨해주고
//아래와 같이 코드에 import 로 추가해준다.
import STRUCTCPP from "cpp-struct-js"; //설명: struct-cpp 모듈
import ICONV from "iconv"; //버퍼를 "utf8" "euc-kr"등 인코딩해주는 모듈
import BUFFTRIM from "node-buffertrim"; //버퍼의 양옆의 "0" 값을 제거, 버퍼트림기능 모듈
Node.JS와 C/C++ TCP/IP 소켓통신할때 참고
(개인적인 방법으로 구성해 보았습니다, 시스템 구성에 따라 다르니 참고용 입니다~!)
//---------------------------------------------------------------------
//---------------------------------------------------------------------
//C/C++
#define T2O =16;
typedef struct _stTest1
{
char test1Str[T2O];
unsigned int test2uint;
void init(){
memset(test1Str, 0, T2O);
test2uint= 0;
}
_stTest1(){ init(); }
}stTest1;
typedef struct _stTest2
{
unsigned int testAuint;
char testBstr[T2O];
unsigned int testCuint;
stTest1 testD[3];
void init(){
testAuint = 0;
memset(testBstr, 0, T2O);
testCuint = 0;
testD[0].init();
testD[1].init();
testD[2].init();
}
_stTest2(){ init(); }
}stTest2;
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//Node.js - struct-cpp
//JS의 Struct의 변수들의 값은 "uint8" 으로 받자.
export const T2O = 16; //대강 String 받을 크기
var stTest1 = new STRUCTCPP("stTest1", [
"test1Str", STRUCTCPP.uint8(T2O), //String
"test2uint", STRUCTCPP.uint8(2), //uint16
]);
var stTest2 = new STRUCTCPP("stTest2", [
"testAuint", STRUCTCPP.uint8(2), //uint16
"testBstr", STRUCTCPP.uint8(T2O), //String
"testCuint", STRUCTCPP.uint8(2), //uint16
"testD", STRUCTCPP.type(stTest1 , 3) //stTest1[3]
]);
//-----------------------------------------------------------------
//encode 값을 넣을때
let dat16_t1 = new Uint16Array([52]);
let dat8_t1 = new Uint8Array(dat16_t1.buffer);
let datStr_t2 = "test가나";
let datStrbuf_t2 = Buffer(datStr_t2);
let dat16_t3 = new Uint16Array([23]);
let dat8_t3 = new Uint8Array(dat16_t2.buffer);
let datStr_p1 = "test다라";
let datStrbuf_p1 = Buffer(datStr_p2);
let dat16_p2= new Uint16Array([123]);
let dat8_p2= new Uint8Array(dat16_p2.buffer);
var bufTest = new Buffer(stTest2.size());
stTest2.encode(bufTest, 0, {
testAuint: dat8_t1, //값:52
testBstr: datStrbuf_t2, //값:"test가나"
testCuint: dat8_t3, //값:23
testD:[
{test1Str: datStrbuf_p1}, //배열 testD[0]->test1Str: "test다라"
{test2uint: dat8_p2}, //배열 testD[1]->test2uint: 123
{test1Str: datStrbuf_t2, test2uint: dat8_t1}, //배열 testD[2]->test1Str: "test가나", test2uint: 52
]
},{endian: "LE"});
//---------------------------------------------------------------
//C/C++ 소켓 TCP/IP 연결 패킷 보낼때.
import NET from "net"; //Node.js -> net
let servAddr = '111.222.333.444'; //주소
let servPort = 2145; //포트
let clientSocket = NET.Socket();
clientSocket.connect(servPort, servAddr, function() {
console.log('Client connected to: ' + servAddr + ':' + servPort);
clientSocket.write(bufTest); //위의 bufTest 버퍼를 보낸다.
});
//-----------------------------------------------------------------
//C/C++ 소켓 TCP/IP 연결 패킷 받을때
var bufTestRevc = null;
clientSocket.on('data', function(data) {
console.log('Client data');
console.log('Client received: ' + data+'##bytelen:');
bufTestRevc = data;
});
//-----------------------------------------------------------------
//decode 값을 가져올때
let decData = stTest2.decode(bufTestRevc, 0, {endian:"LE"}); //"bufTestRevc" 위의 가져온 패킷을 decode 한다.
let stTest2_testAuint_buf = new Buffer(decData.testAuint);
let stTest2_testAuint = stTest2_testAuint_buf.readUIntLE(0, stTest2_testAuint_buf.length); //값: 52
let stTest2_testBstr = new Buffer(decData.testBstr).toString(); //값:"test가나 "let stTest2_testBstr_buf = new Buffer(decData.testBstr);
let stTest2_testBstr = stTest2_testBstr_buf.readUIntLE(0, stTest2_testBstr_buf.length); //값: 23
let testD_0 = decData.testD[0];
let testD_1 = decData.testD[1];
let testD_2 = decData.testD[2];
//testD_2 만 decode 해보겠다.
let testD_2_test1Str = new Buffer(testD_2.test1Str).toString(); //값:"test가나 "
let testD_2_test2uint_buf = new Buffer(testD_2.test2uint);
let testD_2_test2uint = testD_2_test2uint_buf.readUIntLE(0, testD_2_test2uint_buf.length); //값: 52
//이처럼 형변환 문제로 변환할게 많아서 아래 설명 ES6이상 코드스타일로 "class CProtUtil" 에서
//클래스 함수형으로 묶어서 형변환에 맞게 만들어 두었다. 형변환에 필요함수부분은 아래
//설명, 코드를 보면 되겠다.
=================================
=================================
=================================
Util -> class CProtUtil
//ES6이상용으로 Class를 이용하여 cpp-struct-js 에 필요한 형 변환 유틸구현
//(만약 C++과 소켓통신시 struct를 버퍼형으로 보낼때 형변환시 필요)
//Node.js 보안문제로"new Buffer(.)"는 ->"Buffer.from(.), Buffer.alloc(.)"식으로 교체된다.
//ES6 이상 모듈 import, export 사용 아래와같이 node.js[npm] 에서
//(cpp-struct-js, iconv, node-buffertrim)을 인스톨해주고
//아래와 같이 코드에 import 로 추가해준다.
import STRUCTCPP from "cpp-struct-js";
import ICONV from "iconv";
import BUFFTRIM from "node-buffertrim";
//-------------------------
//-------------------------
//CLASS - CProtUtil
export class CProtUtil
{
constructor(){}
static getUINT16toUINT8Arr(val)
{
let dat16 = new Uint16Array([val]);
let dat8 = new Uint8Array(dat16.buffer);
dat16 = null;
return dat8;
}
static getBuffTrim(buf) //"getBuffTrim(.)"버퍼양옆의 빈값 제거
{
return BUFFTRIM.trim(buf);;
}
static getUINT8ArrToUINT16(uint8Arr)
{
let uint8buf = Buffer.from(uint8Arr);
let uint16 = uint8buf.readUIntLE(0, uint8buf.length);
uint8buf = null;
return uint16;
}
static getUINT8ArrToString(uint8Arr, encoding)
{
let iv = new ICONV.Iconv(encoding, 'utf-8');
let uint8buf = CProtUtil.getBuffTrim(Buffer.from(uint8Arr)); //"getBuffTrim(.)"버퍼양옆의 빈값 제거
let str = iv.convert(uint8buf).toString();
uint8buf = null;
iv = null;
return str;
}
static getStringToUINT8Arr(dat, encoding)
{
let iv = new ICONV.Iconv('utf-8', encoding);
let buf = Buffer.from(dat); //let strEncoding = JSCHARDET.detect(buf);
let buf_cvt = iv.convert(buf);
iv = null;
buf = null;
return buf_cvt;
}
static convertStructType(struct, dat)
{
let tmpData = null;
if(dat instanceof Uint8Array) //uint8array buf type
{
tmpData = struct.decode(dat, 0, {endian:"LE"});
}
else {
tmpData = dat;
}
return tmpData;
}
static convertArrDecode(cls, arrDat, cnt, encoding) //class, arrData, cnt, encoding
{
let arr = new Array();
let tmpInfo = null;
for(let i=0; i<cnt; i++)
{
tmpInfo = arrDat[i];
if(tmpInfo)
{
arr.push(cls.getDecode(tmpInfo, encoding));
}
}
return arr;
}
}
=================================
=================================
=================================
cpp-struct-js 를 ES6이상용으로 Class를 이용하여 응용해 보기(1)
(위에 js클래스 CProtUtil 를 이용해서 형변환 사용)
//ES6 이상 모듈 import, export 사용 아래와같이 node.js[npm] 에서(cpp-struct-js, iconv, node-buffertrim)을 인스톨해주고
//아래와 같이 코드에 import 로 추가해준다.
import STRUCTCPP from "cpp-struct-js";
import ICONV from "iconv";
import BUFFTRIM from "node-buffertrim";
//---------------------------------------------------------------------------------------------------------------
//CLASS -> CTTestA
//비공개 변수
let priCTTestA = {
_structObj: null,
};
export class CTTestA //"TestA", "TestB", "TestC"
{
constructor(){}
static get getStruct()
{
if(priCTTestA._structObj == null)
{
priCTTestA._structObj = new STRUCTCPP("TTestA", [
"TestA", STRUCTCPP.uint8(2),
"TestB", STRUCTCPP.uint8(2),
"TestC", STRUCTCPP.uint8(2),
]); //const SZ_TTestA = 6;
}
return priCTTestA._structObj;
}
static getDecode(dat, encoding)
{
let tmpData = CProtUtil.convertStructType(CTTestA.getStruct, dat);
let TestA = CProtUtil.getUINT8ArrToUINT16(tmpData.TestA);
let TestB = CProtUtil.getUINT8ArrToUINT16(tmpData.TestB);
let TestC = CProtUtil.getUINT8ArrToUINT16(tmpData.TestC);
return {TestA , TestB , TestC};
}
}
//-------------------------------------------------------------------------------------------------------------------
//CLASS -> CTDBPsjPktTest
//struct 값 "info" 에 클래스"CTTestA"의 struct 타입으로 넣는다.
=================================
=================================
=================================
cpp-struct-js 를 ES6이상용으로 Class를 이용하여 응용해 보기(2)
(위에 js클래스 CProtUtil 를 이용해서 형변환 사용)
//ES6 이상 모듈 import, export 사용 아래와같이 node.js[npm] 에서(cpp-struct-js, iconv, node-buffertrim)을 인스톨해주고
//아래와 같이 코드에 import 로 추가해준다.
import STRUCTCPP from "cpp-struct-js";
import ICONV from "iconv";
import BUFFTRIM from "node-buffertrim";
=================================
=================================
=================================
// CTDBIRec: //비공개 변수
export const T2O = 16;
let priCTestC = {
_structObj: null,
};
export class CTestC //test1str, test2str, test3uint, test4uint, test5uint
{
constructor(){}
static get getStruct()
{
if(priCTestC._structObj == null)
{
priCTestC._structObj = new STRUCTCPP("TDBIRec", [
"test1str", STRUCTCPP.uint8(T2O), //String
"test2str", STRUCTCPP.uint8(T2O), //String
"test3uint", STRUCTCPP.uint8(2), //uint16
"test4uint", STRUCTCPP.uint8(2), //uint16
"test5uint", STRUCTCPP.uint8(2), //uint16
]); // const SZ_CTestC = 38;
}
return priCTestC._structObj;
}
static getDecode(dat, encoding)
{
let tmpData = CProtUtil.convertStructType(CTDBIRec.getStruct, dat);
let Addr = CProtUtil.getUINT8ArrToString(tmpData.Addr, encoding);
let Name = CProtUtil.getUINT8ArrToString(tmpData.Name, encoding);
let Flag = CProtUtil.getUINT8ArrToUINT16(tmpData.Flag);
let NowU = CProtUtil.getUINT8ArrToUINT16(tmpData.NowU);
let MaxU = CProtUtil.getUINT8ArrToUINT16(tmpData.MaxU);
return {Addr, Name, Flag, NowU, MaxU};
}
}
=================================
=================================
=================================
#기타관련링크
- http://adrichman.github.io/nodejs-parsing-binary-from-the-tcp-layer/
- https://stackoverflow.com/questions/51122724/reading-a-tcp-packet-on-node-js-server
- https://www.npmjs.com/package/struct
- https://www.npmjs.com/package/cpp-struct-js
- https://www.npmjs.com/package/c-struct-js
=================================
=================================
=================================
'WEB > JavaScript' 카테고리의 다른 글
[Node.js] Node.js 웹소켓 nodejs-websocket (0) | 2018.11.05 |
---|---|
[Node.js] iconv 인코딩모듈 설치, 사용 관련 (1) | 2018.10.22 |
[Node.js] Node.js를 WebStorm 을 이용하여 ES6의 import, export 모듈화하여 개발 또는 모듈화 프로그래밍 관련 (0) | 2018.10.01 |
[Node.js] Node.js 소켓, 웹소켓, (TCP/IP),통신 관련 프로그래밍 관련 (0) | 2018.10.01 |
[Node.js] Node.js를 Cloud9에서 구현하기 (socket.io를 통한 채팅 프로그램 적용) (1) | 2018.09.30 |