I'm FanJae.

[Socket] Byte order에 따른 소켓 통신 시 유의할 점 본문

Network/Network Programming

[Socket] Byte order에 따른 소켓 통신 시 유의할 점

FanJae 2025. 6. 3. 17:58

 

1. 바이트 저장 순서 (Byte Order)

- 컴퓨터는 데이터를 메모리에 저장할 때 바이트(Byte) 단위로 나눠 저장한다.

- 여러 바이트로 구성된 데이터 타입은 인접한 메모리 주소에 연속적으로 저장된다.

- 이때,여러 바이트로 구성된 데이터를 메모리에 어떤 순서로 저장할지 정하는 방식을 엔디안(Endian)이라고 한다.

 

2. 엔디안(Endian)

- 앞서 설명한 바와 같이 Endian은 데이터가 메모리에 저장되는 순서를 의미한다.

- Endian은 CPU의 아키텍처의 데이터 저장 방식 설계에 따라 결정된다. 일반적으로, 리틀 앤디안(Little Endian)과 빅 앤디안(Big Endian)의 두가지 방식이 존재한다. 

 

2-1.  빅 엔디안(Big Endian) 방식

- 빅 엔디안 방식은 가장 상위 바이트를 메모리의 가장 낮은 주소에 저장하는 방식이다.

- 바이트 순서를 사람이 숫자를 읽는 방식(왼쪽->오른쪽)과 일치하게 정렬하는 특징이 있으며, 0x0A0B0C0D를 저장하는 경우, 가장 앞 주소에 0x0A가 저장된다.

 

2-2. 리틀 엔디안(Little Endian) 방식

- Little Endian 방식은 가장 하위 바이트를 메모리의 가장 낮은 주소에 저장하는 방식이다.

- 0x0A0B0C0D를 저장하는 경우, 가장 앞 주소에 0x0D가 저장된다.

 

이처럼, CPU의 아키텍처에 따라서 메모리에 어떤 순서로 저장하는지 달라진다. 이에 따라서 서로 다른 시스템 간 소켓 통신을 진행 할 때 유의할 점이 존재한다. 예를들어, Little Endian 기반의 x86 서버가 Big Endian 방식의 네트워크 장비와 통신할 경우, 패킷 데이터가 엉뚱하게 해석될 수 있으므로 바이트 오더 변환이 필수적이다.

 

3. Host Byte Order(호스트 바이트 오더)

- 특정 CPU 아키텍처가 데이터를 메모리에 저장할 때 사용하는 고유의 바이트 순서.

- 즉, 시스템 내부에서 사용되는 엔디안 방식이며, 시스템 간 데이터 교환 시 반드시 고려해야 한다.

 

4. Network Byte Order(네트워크 바이트 오더)

- 네트워크 상에서 데이터를 전송할 때 모든 시스템이 동일한 바이트 순서를 사용하도록 정한 표준 규약이다.

- Big Endian 방식이 채택되어 있다.

 

5. Byte Order 처리 

5-1. C++ (Windows 기준)

#include <iostream>
#include <winsock2.h>

#pragma comment(lib, "Ws2_32.lib")

struct Packet
{
    uint32_t playerID;
};

void readPacket(const char* buffer)
{
    Packet pkt;

    pkt.playerID = ntohl(*reinterpret_cast<const uint32_t*>(buffer));

    std::cout << pkt.playerID << std::endl;
}

int main(void)
{
    // 테스트용 playerID = 1205
    uint32_t playerIdNetOrder = htonl(1205); // 네트워크 바이트 순서로 변환
    const char* buffer = reinterpret_cast<const char*>(&playerIdNetOrder);
    // 임의로 위와 같은 데이터를 받아왔다고 가정.

    readPacket(buffer); // 테스트

    return 0;
}

- winsock2.h의 send()는 buf가 const void *가 아닌 const char *이다. (Linux는 const void *)

- 이는 recv()도 동일하다.

 

5-2. Java

- C,C++은 CPU 아키텍처에 따라 Endian이 결정되는 반면 Java는 다르다.

- Java는 JVM 명세에 따라서, 일관되게 정의되어있다.

- 기본적으로는 Java Byte Code는 Big Endian으로 정의되어 있다.

더보기

※ Network Byte Order 규칙을 따른다면, Java에서는 표준 Java I/O를 사용할때, 수신된 데이터의 Byte Order를 조정할 필요가 없지만, JNI와 같은 Native Library를 사용하는 경우 변환이 필요하다고 한다.

 

 

外. 이미지 출처

- 위키피디아

 

 

Comments