본문 바로가기

프로그래밍/C,C++

바이트오더~ 비트 스트림~

 

byte order ~

 

바이트 오더~

네트웍이나 비트 스트림에서 기본적으로 발생하는 실수 중에 하나이다~ 

 

같은 나라 사람이라면 같은 말을 쓰면 되니 상관없지만

다른 나라 사람들과 의사소통을 위해선 아무래도 공통적으로 쓰는 말을

사용해야 한다. 하필이면 그것이 한국어,한글이 아닌 영어라서 문제지만 -_-;;;

 

 

네트워크 상의 데이터도 마찬가지~

이놈들은 다른건 괜찮은데 short, long 같은 2byte 이상의 숫자에만

서로 해석하는게 틀리다~

 

이런저런거 다빼고~

 

일단 유닉스 시스템은 빅엔디안 시스템이고, 인텔계열은 리틀엔디안 시스템이다.

 

빅엔디안이란 MSB 부터 부호화 되며,

리틀엔디안이란 LSB 부터 부호화 된다.

 

또 뭔소리랴~

말그대로 MSB 는 최상위 비트, LSB 는 최하위 비트를 뜻한다.

 

MSB 부터 부호화가 된다면 말 그대로 앞에 비트부터 차례대로

8bit를 세어 1byte를 만들고 그런 차례대로 부호화 한다는 것이다.

예를 들어 10진수 256 은 00000001 00000000이다~

MSB 부터 부호화해 16진수로 바꾸면 0x0100 .. 그렇다 그냥 차례대로 부호화 된다.

이것이 빅엔디안 방식이 되는 거시다~

 

반면 리틀엔디안에서

LSB부터 8bit를 가져와 1byte를 만드는 순서대로 부호화 하게 된다.

즉, 256은 하위8bit부터 시작해 00000000 00000001 이되며

이는 16진수로 0x0001 로 부호화 되는 거시다~

(가져온 1byte 내의 bit 순서는 바뀌지 않는다.)

 

위 바이트 오더는 메모리에 저장되는 순서 이므로 중요한 개념이다.

 

보기엔 빅엔디안이 좋지만 시스템의 입장에선 리틀엔디안이 좋을 듯 하다~

특히 short값을 long 값으로 캐스팅 할 경우

빅엔디안에선 앞에 2byte를 추가하고, 원래의 값을 뒤로 밀어야 한다.

리틀엔디안에서야 뒤에 2byte 붙이면 끝이고~

 

장단점은 다 있것지만 암튼 그렇다~

 

그럼~ 이런 내용이 어디서 문제가 되느냐~

바로 네트워크 전송이다.

보통 네트워크 전송은 정의된 패킷에 데이터를 채워 사이즈 만큼 전송하는

방식이다.

 

short 값을 전송하면 해당 메모리의 2byte를 전송하게 된다.

수신하는 곳에선 역시 2byte 값을 수신하게 되며, 수신한 값을 메모리에 담는다.

윈도우 클라이언트에서 유닉스 서버로 데이터를 보냈다면

메모리에 담긴 데이터를 같지만 서로 해석하는 방법(순서)의 차이로

다른 값을 나타내게 된다.

 

256(0x0100)을 보냈는데, 수신한곳에선 1(0x0001) 이 되어 버리는 것이다~

 

따라서, 규약에 따라 네트워크로 보낼때는 무조건 빅엔디안으로 보내고

받는 쪽에선 자신의 시스템에 따라 다시 변경해 사용하는 것이 가장 안정적인

방법이다~

 

죽어도 타기종의 시스템과 연결될 일이 없다면, 아무 신경쓰지 않고 써도

무방하겠다~

 

추가로 char 형이나 문자열은 각각 바이트의 집합이기에 위의 오더에 영향을 받지 않는다.

 

벗뜨!!!!! 받은 char형을 long 으로 캐스팅 하면?

 

만약 유닉스 서버에서 보낸 0x00 0x00 0x00 0x01 의 4byte 문자열을 윈도우 클라이언트에서

받았고, 클라이언트는 이 32bit의 값을 가져와 값이 1인지를 검사해야 한다고 생각해 보자.

(보통의 비트 스트림에서 사용하는 방법이다)

 

이를 long으로 캐스팅하면 어떤 값이 나올까? 0x01000000 = 16777216 이 나오게 된다.

 

정확한 값을 얻고자 하면, 4byte의 문자열의 순서를 리틀엔디안 형태로 변경하고,

long으로 캐스팅 해야 할것이다.

또는, 일단 long으로 캐스팅을 하고, 다시 ntohl() 등의 변환 함수로 바이트 오더를

변경해 주면 되겠다~

'프로그래밍 > C,C++' 카테고리의 다른 글

[C#] 파일 읽고,쓰기 기초  (0) 2013.09.12
[C#] 이미지 처리 기본 사항들  (0) 2013.09.12
[C#] 이벤트  (0) 2013.09.12
[C#] 폼 띄우기  (0) 2013.09.12
GCC 옵션  (0) 2011.07.21
POSIX 쓰레드 함수들  (0) 2010.04.16
[Linux] 세마포어 설정  (0) 2010.04.15
[Linux] 라이브러리  (0) 2010.01.28
delete obj, delete [] obj 차이  (0) 2009.06.04
[C]  (0) 2009.06.04