CPU에 따라서 같은 값을 저장하는 방식이 달라질 수 있습니다.
이런 부분을 고려하지 않고서 데이터를 송수신하면 문제가 발생할 수 있습니다. 저장 순서가 다르다은 것은 전송되어온 데이터의 해석순서가 다름을 뜻하기 때문입니다.
바이트 순서와 네트워크 순서
CPU가 데이터를 메모리에 저장, 해석하는 방식은 다음과 같이 두 가지로 나뉩니다.
- 빅 엔디안(Big Endian): 상위 바이트의 값을 작은 번지수에 저장
- 리틀 엔디안(Little Endian): 상위 바이트의 값을 큰 번지수에 저장
0x20번지를 시작으로 4바이트 int형 정수 0x12345678을 저장한다고 가정하고 예시를 들어보겠습니다.
빅 엔디안 방식의 CPU는 다음의 형태로 메모리에 저장합니다.
리틀 엔디안 방식의 CPU는 다음과 같은 방식으로 저장합니다.
이렇듯 데이터 저장방식은 CPU마다 다릅니다. 따라서 CPU의 데이터 저장방식을 의미하는 호스트 바이트 순서는 CPU에 따라 차이가 납니다. 이렇게 호스트 바이트 순서가 다른 두 CPU가 데이터를 주고받을 때 발생할 수 있는 문제점을 다음 그림을 통해 보겠습니다.
위 그림과 같이 데이터를 송신하는 쪽과 수신하는 쪽이 같은 데이터를 다른 방식으로 해석함을 볼 수 있습니다. 따라서, 네트워크를 통해서 데이터를 전송할 때에는 통일된 기준으로 데이터를 전송하기로 약속했으며, 이 약속을 네트워크 바이트 순서라 합니다. 네트워크 바이트 순서의 약속은 매우 간단합니다. 그냥 네트워크상으로 데이터를 전송할 때에는 데이터의 배열을 빅 엔디안 기준으로 변경해서 송수신하기로 한 것입니다.
바이트 순서의 변환
이제 sockaddr_in 구조체 변수에 값을 채우기 앞서 네트워크 바이트 순서로 변환해서 저장해야 하는 이유는 설명이 됐을 것입니다. 바이트 순서의 변환을 돕는 함수들을 소개하겠습니다.
unsigned short htons(unsigned short); // host to network short
unsigned short ntohs(unsigned short); // network to host short
unsigned long htonl(unsigned long); // host to network long
unsigned long ntohl(unsigned long); // network to host long
간단한 예제 코드를 통해 위에서 소개한 함수들을 사용해보겠습니다.
#include <stdio.h>
#include <arpa/inet.h>
int main(char* argv[]) {
unsigned short host_port = 0x1234;
unsigned short net_port;
unsigned long host_addr = 0x12345678;
unsigned long net_addr;
net_port = htons(host_port);
net_addr = htonl(host_addr);
printf("Host ordered port: %#x\n", host_port);
printf("Network ordered port: %#x\n", net_port);
printf("Host ordered address: %#lx\n", host_addr);
printf("Network ordered address: %#lx\n", net_addr);
return 0;
}
실행 결과는 아래와 같습니다. 이 결과는 리틀 엔디안 기준으로 정렬하는 CPU에서의 실행결과입니다.
그런데 이 때, 데이터 송수신 기준이 네트워크 바이트 순서이다 보니, 데이터를 전송하기 전에 네트워크 바이트 순서로 데이터를 변경해줘야 하는 게 아닌가 하는 의문이 들 수도 있지만, 이는 데이터 송수신 과정에서 알아서 변환되므로 sockaddr_in 구조체 변수에 데이터를 채울 때 외에는 이러한 것을 신경 쓸 필요가 없습니다.
'네트워크 프로그래밍 > C' 카테고리의 다른 글
[네트워크 프로그래밍/C] TCP와 UDP에 대한 이해 (0) | 2022.02.22 |
---|---|
[네트워크 프로그래밍/C] 인터넷 주소의 초기화와 할당 (0) | 2022.02.22 |
[네트워크 프로그래밍/C] 주소정보의 표현 (0) | 2022.02.17 |
[네트워크 프로그래밍/C] 소켓에 할당되는 IP주소와 PORT 번호 (0) | 2022.02.17 |
[네트워크 프로그래밍/C] 소켓의 프로토콜과 그에 따른 데이터 전송 특성 (0) | 2022.02.17 |