본문 바로가기
알고리즘 구상

[알고리즘] 헥사데이터 문자열 변환 송수신 (문자열에 0x00값 포함)

by 코딩히어로 2021. 3. 12.
728x90

서버를 개발하다 보면 대부분의 프로그램 구조는 송수신을 처리하는 게 대부분이라고 할 수 있습니다

 

단연 서버뿐만 아니라 여러 가지 임베디드나 어플 등 모든 통신에서 데이터를 통신할 때

 

문자열 ASCII로만 송수신을 한다면 크게 문제사항은 없을 것이나 예를 들어 데이터 값에 0x00 값이 들어있는 경우,

 

이런 경우에는 데이터 전송 시에 0x00 뒤쪽 데이터는 다 날아가는 등의 문제를 겪어보셨을 거예요

 

A = [ 0x01 0x02 0x00 0x03 0x04 0x05 ]

 

위와 같은 데이터가 있고 통신을 했을 때 1byte식 직접 전송하고 직접 받는다면 크게 문제는 없지만

 

예를 들어서 Mysql같은 sql구문에 넣어야 하는 경우 등을 생각해보면 문제는 달라집니다

 

 

 

1) 문제점 고민


자 어떠한 문제가 생기느냐 하면 예를들어 위에서 설명한 A 데이터를 Sql구문을 통해

 

Mysql 쪽에 전달을 해야 되는 상황이라면 어떻게 될까요??

 

sprintf(sql, "insert into TEST(data) values('% s')", A);

 

기본적으로 c언어 상에서 위의 구문으로 적용을 했다고 해 보도록 하죠

 

그렇다면 실제로 실행을 했을 때에 TEST 테이블에 입력되는 값은

 

0x01 0x02 가 될 것입니다

 

왜인지 잘 생각해보면 우리가 sprintf를 통해 sql구문에 입력해 줄 때에

 

A를 입력해주는 타입이 % s이기 때문입니다

 

%s 즉 문자열을 입력하는데 0x00은 문자열의 끝을 나타내기 때문에

 

0x00 이하의 모든 데이터는 무시되게 되는 것이죠

 

엥? 그러면 하나씩 넣어주면 되지 않나요 라고 하실 수도 있습니다

 

sprintf(sql, "insert into TEST(data) values('% c% c% c% c% c% c')", A[0], A[1], A[2], A[3], A[4], A[5], A[6]);

 

물론 위와 같이 한다면 sql이라는 문자 배열에는 원하는 대로 6byte의 A데이터가 전부 입력이 됩니다

 

하지만 여기서도 함정이 있는 것은 sql을 실행할 때에 생겨납니다

 

c언어 프로그램 환경의 mysql에 위 구문을 실행하면

 

mysql_query(sql);

 

당연히 될 거라 생각되겠지만 mysql_query 자체가 문자열을 전달하기에

 

insert into TEST.... 0x010x02

 

이렇게 다시 0x00을 만나는 뒷라인은 문자열 종료로 판단하게 됩니다

 

 

 

2) 해결방법은?


해결 방법은 의외로 간단합니다

 

바로 이 데이터들을 한번 가공해서 사용한다는 개념을 도입하는 것이죠

 

예를 들어 데이터를 전송할 때에는

 

헥사 값 >> 문자열 ASCII 변환

 

데이터를 수신할 때에는

 

문자열 ASCII >> 헥사 값 변환

 

의 로직을 통해서 데이터를 가공하면 문제를 해결할 수 있어요

 

헥사 값 0x00을 변환하는 방법으로는 0x00을 0x30 0x30으로 만들어주면 결국 ASCII 00이 되겠네요

 

그리고 다시 수신받은 쪽에 ASCII 00은 0x00으로 변환하는 작업을 통해서 온전한 헥사 값을 사용할 수 있습니다

 

 

 

3) 실제 사용한 로직


제 경우에는 서버와 임베디드가 통신하는 시스템상에서

 

임베디드의 프로토콜 구성이 헥사 값으로 구성되어 있었고 100byte가 넘는 데이터를 송수신해야 했습니다

 

그리고 그중에는 당연히 0x00 값들이 무수히 많이 있었습니다

 

임베디드에서 데이터 값이 들어오면 아래와 같이 변환해 주었습니다

 

위 코드는 제가 운영하는 서버에 실제로 사용된 로직으로 read_message [4]는 데이터 Length를 의미하며

 

1byte의 헥사 값을 2byte의 ASCII값으로 가공하는 코드입니다

 

변환이 완료된 뒤에 전송하는 데이터는 read_trans_message 버퍼입니다

 

자 그렇다면 수신해서 헥사 값으로 변환 하는 코드도 필요하겠죠

 

수신된 trans_befor_data버퍼를 2byte씩 묶어서 1byte의 헥사 값으로 변환해 주는 코드입니다

 

이렇게 변환이 완료되면 온전한 hex 데이터 값들이 write_msg버퍼에 저장되고 이

 

wirte_msg를 기준으로 데이터를 사용하시면 됩니다

 

제가 처음 이문제를 접했을 때까지만 해도 아무리 구글링을 하고 비슷한 문제를 찾아도

 

해결방법이 나온 내용들을 찾지 못했고 이러한 로직을 만들어서 지금은 여러가지 프로젝트에 적용 중입니다

 

이 내용이 저와 비슷한 문제를 겪는 개발자분들에게 도움이 되길 바랍니다

728x90
반응형

댓글