C

데이터 통신 - 바이트스터핑 구현(C)

corin13 2024. 2. 10. 19:24

아스키 코드를 보면 아래 그림과 같이 STX, ETX와 같은 특정 문자들을 사용하는 것을 알 수 있다.

바이트 스터핑이란 특정 문자가 실제 데이터 몸체에서도 동일 문자가 나오는 것을 방지하기 위해 송식 측에서 우연히 나타나는 DLE 문자 바로 직전에 여분의 DLE를 삽입하여 구분시키는 것을 말한다.

 

출처 : http://www.ktword.co.kr/test/view/view.php?m_temp1=12

 

 예를 들어 ASCII코드 1B와 7E 값을 가지는 통신 제어 문자가 있다 가정했을 때, 데이터에 우연히 1B 혹은 7E가 들어갔을 때 이게 제어 문자로서 1B(or 7E)인지 그냥 데이터로서 1B인지 알 수 없으므로 앞에 1B를 추가시켜서 구분시키는 것이다.

 

아래 그림 속 예제를 보면 알 수 있는데, 데이터(D)를 보면, 데이터 속에 7E와 1B가 들어가 있다. 이처럼 데이터 속에 통신 제어 문자와 동일한 문자가 들어갔을 때 구분하기 위해 송신 측(Tx)에서 해당 문자들 앞에 DLE로 1B가 추가해주는 것을 알 수 있다.(핑크색 1B)

이렇게 송신 측(Tx)에서 보내진 문자를 수신 측(Rx)에서는 다시 복원을 시켜야 하는데, 추가된 1B를 제거해주면 원본 데이터가 나온다.

 

대충 이런 규칙

코드로 구현하기 앞서 16진수 1B를 진법 변환시  27의 값을, 7E는 126의 가지는 것을 알 수 있다.

그래서 입력을 16진수로 받는 게 아닌 편하게 10진수로 받고 그걸 16진수로 출력하는 식으로 구현하였다.

데이터(D)
Tx측. 27은 1B로, 126은 7E로 나타난다.

데이터가 들어왔을 때, 1B 혹은 7E 앞에는 DLE로 1B가 붙어 나타나는 것을 볼 수 있다.

수신측

그리고 수신 측에서는 이렇게 추가된 1B를 제거하여 원본 데이터를 얻는다.

 

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(void)
{
    unsigned char data[10][10] = {NULL,};   //데이터
    unsigned char tx[10][20] = { NULL, };   //송신
    unsigned char rx[10][20] = { NULL, };   //수신

    srand(time(0));

    /* 데이터 생성*/
    for (int i = 0; i < 10; i++)    //data[0]~data[9]까지 삽입
    {   int len = 1+rand() % 9;     //각 데이터당 길이를 랜덤하게
       
        printf("arr[%d], %d개의 데이터를 입력하세요. ",i,len);
        for (int j = 0; j < len; j++)   //data[i]에 데이터 삽입하는 부분
        {  
            scanf("%d", &data[i][j]);   //일단 정수로 입력 받음
        }
    }
    printf("\n");


    /*tx 구현*/
    for (int i = 0; i < 10; i++)
    {
        int cnt = 0;
        for (int j = 0; data[i][j]!=NULL; j++)
        {
            if ((data[i][j] == 27) || (data[i][j] == 126))  //원문 데이터에 1B 혹은 7E가 있냐?
            {
                tx[i][j+cnt] = 27;  //있으면 1B 추가해주기
                cnt++;
                tx[i][j + cnt] = data[i][j];
            }
            else
            {
                tx[i][j + cnt] = data[i][j];
            }
        }
    }

    /*tx 결과*/
    for (int i = 0; i < 10; i++)
    {
        printf("TX | i = %d, data : ", i);
        for (int j = 0; tx[i][j] != NULL; j++)
        {
            printf("%02X ", tx[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    /*rx 구현*/
    for (int i = 0; i < 10; i++)
    {
        int cnt = 0;
        for (int j = 0; tx[i][j+cnt]!=NULL;j++)
        {
            if ((tx[i][j + 1+cnt] == 126) || ((tx[i][j+cnt] == 27) && (tx[i][j + 1+cnt] == 27)))        // 7E가 나오거나 1B가 연속해서 나오냐?
            {
                for (int k = j; tx[i][k] != NULL; k++)
                {
                    rx[i][k] = tx[i][k + 1+cnt];    //1B 제거(한 칸씩 당기기)
                }
                cnt++;
            }
            else
            {
                rx[i][j] = tx[i][j + cnt];
            }
        }
    }

    /*rx 결과*/
    for (int i = 0; i < 10; i++)
    {
        printf("RX |  i = %d, data : ",i);
        for (int j = 0; rx[i][j] != NULL; j++)
        {
            printf("%02X ", rx[i][j]);
        }
        printf("\n");
    }
    return 0;
}