2.3 IPv4 주소 변환 [TCP/IP 소켓 프로그래밍 with 윈도우즈]

IPv4 주소는 최종 사용자가 기억하기 쉽게 “127.0.0.1”처럼 0에서 255사이의 4개의 정수를 점(.)으로 구분하여 문자열로 표현하고 있습니다. 하지만 이는 기억하기 쉽게 만든 표현 방식으로 실제 IPv4 주소는 4바이트 정수 값입니다.

윈속에서는 문자열로 표현한 주소를 네트워크 바이트 정렬 방식의 4바이트 정수로 변환하는 함수와 역으로 네트워크 바이트 정렬 방식의 4바이트 정수를 문자열로 변환하는 함수를 제공하고 있습니다.

문자열로 표현한 IPv4 주소를 네트워크 바이트 정렬 방식의 4바이트 정수로 변환
unsigned long inet_addr(const char *cip);
네트워크 바이트 정렬 방식의 4바이트 정수의 IPv4 주소를 문자열 주소로 표현
char *inet_ntoa(struct in_addr in);
네트워크 바이트 정렬 방식의 4바이트 정수의 IPv4 주소를 표현할 때 사용하는 구조체
typedef struct in_addr {
        union {
                struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { USHORT s_w1,s_w2; } S_un_w;
                ULONG S_addr;
        } S_un;
#define s_addr  S_un.S_addr // TCP/IP에서 가장 많이 사용
#define s_host  S_un.S_un_b.s_b2   // host on imp
#define s_net   S_un.S_un_b.s_b1   // network
#define s_imp   S_un.S_un_w.s_w2  // imp
#define s_impno S_un.S_un_b.s_b4 // imp #
#define s_lh    S_un.S_un_b.s_b3    // logical host
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;

IN_ADDR 형식 이름은 구조체 struct in_addr을 타입 재지정한 것입니다. 그리고 내부의 매크로로 s_addr을 정의하였는데 TCP/IP 통신에서 가장 많이 사용하는 매크로 멤버입니다.

예를 들어 네트워크 바이트 정렬 방식의 4바이트 정수로 표현한 IPv4 주소가 0x12345678일 때 IN_ADDR 형식 변수에 표현하면 다음처럼 표현할 수 있습니다.

IN_ADDR addr;
addr.s_addr = htonl(0x12345678);
//IPv4 주소 변환
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32")
int main()
{
    WSADATA wsadata;
    WSAStartup(MAKEWORD(2,2),&wsadata);	
    
    IN_ADDR addr;
    addr.s_addr = htonl(12<<24 | 34<<16 | 56<<8 | 78);//12.34.56.78
    printf("%s\n",inet_ntoa(addr));//IPv4 주소를 문자열로 변환

    u_int naddr = inet_addr("192.168.34.0"); //문자열을 IPv4 주소로 변환
    u_int haddr = ntohl(naddr); //호스트 바이 정렬로 변환
    printf("%d.%d.%d.%d\n",haddr>>24, (u_char)(haddr>>16),(u_char)(haddr>>8),(u_char)(haddr));

    WSACleanup();
    return 0;
}

실행 결과

12.34.56.78
192.168.34.0