본문 바로가기

programmer/COM

C Socket 사용시 주의점

Endian 맞추기

C에 TCP Socket에서는 Default으로 Big Endian을 사용한다 때문에 Port 나 IP 정보는 BigEndian으로 날아가는데 칩셋에 따라 Endian이 바뀌기 때문에 해당 칩셋을 확인 후에 보내는 곳의 칩셋과 받는 곳의 칩셋을 맞추어 보내주어야 한다.
동일 개발환경이라면 사실 신경 안 써도 되는 부분이며 주의사항만 알고 개발하면 된다.(Endian 관련 블로그가 많다)

**만약 주고받는 곳 중 하나가 임베디드 시스템이라면 PC 쪽에서 변환하거나 받는 것을 추천한다.(메모리 사용량 최소화)

Write/ read 사용 시 주고받는 메모리 사이즈 맞추기

보내는 Packet size와 받는 Packet 설정 size가 맞아야 한다.

받는 버퍼의 초과 분만큼 read를 더 수행한다. 전략적으로 나누어 받는 방법도 있지만 이와 같은 라이브러리 스펙을 이해해야 정상 데이터를 수집할 수 있다.

Union 사용

구조체를 사용해 데이터를 관리하고 송수신까지 하고 싶을 때 union을 사용하면 쉽게 Buffer Data를 처리할 수 있다. 

<<보낼 때>>
//데이터 처리할 때는 기존 구조체처럼 사용
P_convert cc;
cc.P_body.cheader.msgID = 1;
cc.P_body.cheader.type = 2;
cc.P_body.cheader.data_size = 3;

//보낼때는 Union으로 버퍼 배열만 보내면 데이터가 그대로 전송된다.
write(sock, cc.buffer, sizeof(cc.buffer));
        
<<받을 때>
//버퍼사이즈를 맞추고 데이터 read
str_len=read(sock, packet_msg, BUF_SIZE);
if (str_len==-1)
return (void*)-1;
//Union 생성하고 데이터를 받는다.
P_convert cc;
for(i = 0 ; i< BUF_SIZE; i++)
{
cc.buffer[i] = packet_msg[i];
}

sprintf(test_msg, "%d %s", cc.P_body.cheader.msgID, cc.P_body.data);
packet_msg[str_len]=0;
fputs(test_msg, stdout);

Union에 대한 자세한 내용은 여기에서 알 수 있다.

Struct, Union 사용 시 주의

struct나 Union 내부에서 사용된 배열은 초기화를 따로 해주어야 한다. Class처럼 생성자가 있으면 좋겠지만 Stuct는 생성 이후에 메모리 구조가 생기므로 선언 후에 초기화를 따로 해주어야 한다.

간단하게 for 문을 돌려 0으로 초기화하는 방법도 있고 memset을 활용해 메모리를 초기화할 수 있다.

초기화를 안 해서 발생되는 문제점은 예를 들어 문자열을 송신할 때 초기화하지 않은 메모리에는 쓰레기 값(알 수 없음)이 들어가 있는 상태로 메시지를 송, 수신할 수 있다. 따라서 정확한 페킷 전달을 위해서는 초기화한 후에 사용하는 것을 추천한다.

misraC 룰 적용받지 않는다면 편하게 memset을 사용하자

메모리 할당을 통한 초기화

 

반응형
사업자 정보 표시
라울앤알바 | 장수호 | 서울특별시 관악구 봉천로 13나길 58-10, 404호(봉천동) | 사업자 등록번호 : 363-72-00290 | TEL : 010-5790-0933 | Mail : shjang@raulnalba.com | 통신판매신고번호 : 2020-서울관악-0892호 | 사이버몰의 이용약관 바로가기

'programmer > COM' 카테고리의 다른 글

Blocking, NonBlocking, Sync, AnSync 차이  (0) 2020.10.21
도구 평가 인증 종류  (0) 2020.07.28
CAPL 사용 방법 및 예제  (4) 2020.03.17