2.4 로컬 호스트 IP 주소 얻어오기 [TCP/IP 소켓 통신 프로그래밍 with 윈도우즈]

이번에는  윈속 라이브러리를 이용하여 자신의 로컬 호스트 IP 주소를 얻어오는 함수를 만들어 보아요.

먼저 사용할 함수들을 알아봅시다. 호스트 이름을 얻어오는 함수로 gethostname을 제공합니다. 그리고 호스트 이름을 입력 인자로 호스트 엔트리 정보를 얻어오는 gethostbyname 함수를 제공합니다. 호스트 엔트리 정보에는 h_addr_list에 호스트의 주소 목록을 접근할 수 있으며 h_addrtype을 통해 호스트 주소 타입을 알 수 있습니다.

호스트 이름을 얻어오는 함수
int gethostname(char * name,int namelen);
실패 시: -1(SOCKET_ERROR) 반환
호스트 엔트리를 얻어오는 함수
struct hostent *gethostbyname(const char *name);
호스트 엔트리 구조체
struct  hostent {
        char    * h_name;           // 호스트 이름
        char    ** h_aliases;       // 호스트 별칭 목록
        short   h_addrtype;         //하드웨어 타입, IPv4는 PF_INET
        short   h_length;           //하드웨어 주소 길이
        char    ** h_addr_list;     //하드웨어 주소 목록
};

다음은 로컬 호스트의 디폴트  IP 주소를 얻어오는 함수를 구현하여 테스트한 소스 코드입니다.

//디폴트 IPv4 주소 얻어오기
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>

#pragma comment(lib,"ws2_32")
IN_ADDR GetDefaultMyIP();
int main()
{
    WSADATA wsadata;
    WSAStartup(MAKEWORD(2,2),&wsadata);	
    IN_ADDR addr;

    addr = GetDefaultMyIP();//디폴트 IPv4 주소 얻어오기
    printf("%s\n",inet_ntoa(addr));//IPv4 주소를 문자열로 출력
    
    WSACleanup();
    return 0;
}

IN_ADDR GetDefaultMyIP() 
{
    char localhostname[MAX_PATH];
    IN_ADDR addr={0,};

    if(gethostname(localhostname, MAX_PATH) == SOCKET_ERROR)//호스트 이름 얻어오기
    {
        return addr; 
    }
    HOSTENT *ptr = gethostbyname(localhostname);//호스트 엔트리 얻어오기
    while(ptr && ptr->h_name)
    {
        if(ptr->h_addrtype == PF_INET)//IPv4 주소 타입일 때
        {
            memcpy(&addr, ptr->h_addr_list[0], ptr->h_length);//메모리 복사
            break;//반복문 탈출
        }
        ptr++;
    }
    return addr;
}

로컬 호스트에 있는 IPv4 주소 목록을 출력한다면 다음과 같이 작성할 수 있어요.

//로컬 호스트 IPv4 주소 얻어오기
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#pragma warning(disable:4996)

#pragma comment(lib,"ws2_32")
void ViewLocalHostIPv4();
int main()
{
    WSADATA wsadata;
    WSAStartup(MAKEWORD(2, 2), &wsadata);    

    ViewLocalHostIPv4();

    WSACleanup();
    return 0;
}

void ViewLocalHostIPv4()
{
    char localhostname[MAX_PATH];
    IN_ADDR addr = { 0, };

    if (gethostname(localhostname, MAX_PATH) == SOCKET_ERROR)//호스트 이름 얻어오기
    {
        return;
    }
    HOSTENT* ptr = gethostbyname(localhostname);//호스트 엔트리 얻어오기
    while (ptr && ptr->h_name)
    {
        if (ptr->h_addrtype == PF_INET)//IPv4 주소 타입일 때
        {
            for (int index = 0; ptr->h_addr_list[index]; index++)
            {
                memcpy(&addr, ptr->h_addr_list[index], ptr->h_length);//메모리 복사
                printf("%s\n", inet_ntoa(addr));
            }
        }
        ptr++;
    }
}