본 문서는
1. 바이너리(Binary) 데이터 타입과 텍스트(Text) 데이터 타입의 차이
2. 데이터 전송을 위한 변환 과정
3. Encoding과 Decoding 구현 예제(SmartSerialPort 사용)
순서로 진행합니다.
다양한 통신 환경에서 데이터 송신 시 데이터를 전송하기 전에 데이터의 인코딩(원데이터→바이트 배열)이 필요하며 데이터 수신 시 수신한 데이터를 원본 데이터로 되돌리는 처리인 디코딩(바이트 배열→원데이터)이 필요합니다. 데이터 인코딩/디코딩 방식에 따라 데이터 타입이 Binary 데이터 타입 또는 Text 데이터 타입으로 나뉩니다.
바이너리(Binary) 데이터 타입 | 텍스트(Text) 데이터 타입 |
---|---|
Binary 데이터 타입은 데이터를 이진화하여 전송하며 Text 타입에 비해 훨씬 적은 공간을 차지하고, 인코딩/디코딩 속도가 빠릅니다. 하지만 이진 데이터이므로 가독성이 떨어지고 관리 및 디버깅이 어렵습니다. | Text 데이터 타입은 데이터를 ASCII, Unicode 등의 Text로 처리하여 전송하는 방식으로 인간이 이해할 수 있는 언어를 사용하기 때문에 가독성이 높고 관리 및 디버깅이 쉽습니다. 하지만 Binary 타입에 비해 많은 공간을 요구하고 인코딩/디코딩 속도가 느립니다. |
예를 들어 32비트 부동 소수점값 IEEE754 형식의 데이터 0x40490FDB를 전송하려면, Binary 데이터 타입의 경우 4바이트의 크기지만 Text 데이터 타입의 경우 3.1415927를 전송해야 하므로 ASCII의 경우 9바이트 크기가 됩니다.(Unicode의 경우 18Byte)

2. 데이터 전송을 위한 변환 과정
일반적으로 데이터를 전송하기 위해 Binary화하여 처리하게 됩니다. 아래는 Binary Data의 인코딩 및 디코딩 처리에 관한 설명입니다.


[표] 송/수신 데이터의 프레임 구조 예시
Encoding | Decoding | |
---|---|---|
수치 데이터 |
수치 데이터를 Encoding하기 위해서 BitConverter 클래스를 이용하여 데이터 포맷에 따라 쉽게 변환할 수 있습니다. | 수치 데이터를 Decoding하기 위해서 BitConverter 클래스를 이용하여 데이터 포맷에 따라 쉽게 변환할 수 있습니다. |
// 수치 데이터 fTem에 float(부동 소수점) 데이터 입력 float fTem = 36.5f; // Binary 데이터로 변환 byte[] retBinaryData = BitConverter.GetBytes(fValue); |
// 바이트 배열의 지정된 위치로 반환 후 // float형으로 변환 float fTem1 = BitConverter.ToSingle(retBinaryData, 0); |
|
문자 데이터 |
문자 데이터를 Encoding하기 위해서는 Encoding 클래스를 이용해 문자 인코딩 방식을 선택하여 쉽게 변환할 수 있습니다. | 문자 데이터를 Decoding하기 위해서는 Encoding 클래스를 이용해 문자 인코딩 방식을 선택하여 쉽게 변환할 수 있습니다. |
// String strMsg 선언 string strMsg; // fTem에 float(부동 소수점) 데이터 입력 float fTem = 36.5f; // fTem를 String(소수점 포맷)으로 strMsg에 저장 strMsg = fTem.ToString("0.000000000000000"); // Binary 데이터로 변환 byte[] byMsgLen = Encoding.Unicode.GetBytes(strMsg); |
// 바이트 배열의 지정된 위치로 반환 후 string형으로 변환 string strMsg1 = Encoding.Unicode.GetString(byMsgLen, 0, byMsgLen.Length); // 디코딩된 문자열을 float(부동 소수점)으로 변환 float fTem1 = Convert.ToSingle(strMsg1); |
|
구조체 데이터 |
구조체 데이터를 Encoding하기 위해서는 BitConverter 클래스(string 이외)와 Encoding 클래스(string)를 이용하면 됩니다. | 구조체 데이터를 Decoding하기 위해서는 BinaryReader reader를 이용하면 됩니다. |
private struct StructureData {
// 정수형 타입(채널)
}public int iCh; // 실수형 타입(온도) public float fTem; // 문자열 길이를 저장하기 위해 선언 public byte byMsgLen; // 문자열 타입(메세지) public string strMsg; // 인자로 변환될 구조체 데이터를 // 입력하면 바이트 배열을 리턴한다. private byte[] StructureToByte(StructureData sData) {
// 전체 바이트 배열 크기 계산:
} // int(4) + float(4) + byte(1) + 유니코드 문자열(sData.strMsg.Length * 2) byte[] byteRAW = new byte[sizeof(int) + sizeof(float) + sizeof(byte) + (sData.strMsg.Length * 2)]; // 유니코드 문자열 길이(문자 수 × 2) sData.byMsgLen = (byte)(sData.strMsg.Length * 2) // 구조체 멤버 각각 Byte 배열로 변환하여 // 하나의 스트림(1차원 배열)로 만들기 위해 복사한다. // 채널(정수형) 바이트로 변환 및 복사 Array.Copy(BitConverter.GetBytes(sData.iCh), 0, byteRAW, 0, sizeof(int)); // 온도(실수형) 바이트로 변환 및 복사 Array.Copy(BitConverter.GetBytes(sData.fTem), 0, byteRAW, sizeof(int), sizeof(float)); // 문자열(메세지) 바이트로 변환 및 복사 Array.Copy(Encoding.Unicode.GetBytes(sData.strMsg), 0, byteRAW, sizeof(int) + sizeof(float) + sizeof(byte), (sData.strMsg.Length * 2)); // 일반적으로 문자열의 끝을 NULL문자를 확인하여 구분하지만 // BinaryReader.ReadString 메소드는 문자열 앞부분에 // 1Byte로 인코딩된 길이가 포함되어 인코딩됩니다. // 자세한 내용은 MSDN을 참고하시기 바랍니다. byteRAW[sizeof(int) + sizeof(float)] = sData.byMsgLen; return byteRAW; |
private struct StructureData { public int iCh;
}public float fTem; public byte byMsgLen; public string strMsg; // 인자로 변환될 바이트 배열을 입력하면 // 구조체 데이터를 리턴합니다. StructureData ByteToStructure (byte[] data) { StructureData BinaryReader1 = new StructureData();
}// 기본 데이터 형식을 특정 인코딩의 이진값으로 읽음 using (BinaryReader reader = new BinaryReader (new MemoryStream(data, false), Encoding.Unicode)) {
// 현재 스트림에서 부호있는 4바이트 정수를 읽기(iCh)
}BinaryReader1.iCh = reader.ReadInt32(); // 현재 스트림에서 4바이트 부동 소수점값을 읽기(fTem) BinaryReader1.fTem = reader.ReadSingle(); // 현재 스트림에서 지정된 길이만큼의 문자열 읽기(strMsg) BinaryReader1.strMsg = reader.ReadString(); return BinaryReader1; |
※ 일반 데이터(수치, 문자)와 구조체 데이터는 코딩은 달라도 바이너리 데이터는 동일합니다.
3. Encoding 과 Decoding 구현 예제(SmartSerialPort 사용)

본 예제는 IEC-Series를 사용하여 구조체 데이터를 바이트 배열로 변환하여 송신한 뒤, 수신된 바이트 배열을 구조체로 변환하여 표시하는 예제입니다.
[STEP-1] IEC-Series를 1대만 사용할 경우, 통신에 사용할 포트의 TX 와 RX를 서로 연결 합니다.
IEC-Series를 2대 사용할 경우, 각 장치의 통신 포트를 서로 연결합니다.
[STEP-2] 결선한 포트의 PortNo(포트 넘버)와 BaudRate(통신 속도)를 지정합니다.
[STEP-3] Open 버튼을 클릭하여 통신 포트를 오픈합니다.
[STEP-4] 송신 데이터의 수정을 위해 각 라벨을 클릭한 후 SmartKeyboard 를 사용하여 각각 채널(Int), 온도(float), 메시지(string) 형식에 맞는 Value를 입력합니다.
[STEP-5] Send 버튼을 클릭하여 입력한 데이터가 수신 측 SmartListBox에 정상 표시되는지 확인합니다.
※ 장치를 1대만 사용하는 경우, 송신한 데이터가 바로 자신의 SmartListBox에 표시됩니다.