[네트워크] 도메인을 ip로 바꾸기

박성빈·2024년 5월 21일
0

네트워크

목록 보기
3/3

소켓 프로그래밍을 짜는데 자꾸 도메인을 ip로 바꿀 때 어떤 함수를 썼고 어떤 방식으로 코드를 짰는지 헷갈려서 정리를 하려합니다.

1. 도메인 -> IP

도메인을 IP 구조체로 바꿀 때 옛날 책을 보면 gethostbyname이라는 함수를 사용하라고 합니다.
하지만 이 함수는 유니코드를 지원하지 않고 너무 옛날 방식이기 때문에 MSDN에서도 해당 함수를 보면 이렇게 써있습니다.

참고 : gethostbyname 함수는 getaddrinfo 함수를 도입하여 더 이상 사용되지 않습니다. Windows Sockets 2 애플리케이션을 만드는 개발자는 gethostbyname 대신 getaddrinfo 함수를 사용해야 합니다.

그러므로 getaddrinfo 함수를 쓰면 되는 것이죠.
우선 GetAddrInfo 함수를 쓰려면 일단 ws2tcpip.h 헤더를 인클루드 해줘야 합니다.

이 함수는 유니코드도 지원하고 ANSI 문자열도 지원합니다.
GetAddrInfo 함수를 쓰면 알아서 환경에 따라 변환해 줍니다.
우선 유니코드 기반으로 쓰는 것을 설명하겠습니다.

함수 형태는 다음과 같습니다.

INT WSAAPI GetAddrInfoW(
  [in, optional] PCWSTR          pNodeName,
  [in, optional] PCWSTR          pServiceName,
  [in, optional] const ADDRINFOW *pHints,
  [out]          PADDRINFOW      *ppResult
);

1) pNodeName : 여기에 도메인 이름을 넣습니다.
2) pServiceName : 문자열로 표시되는 서비스 이름 또는 포트 번호를 포함하는 NULL로 종료된 유니코드 문자열에 대한 포인터입니다.
3) pHints : 호출자가 지원하는 소켓 유형에 대한 힌트를 제공하는 addrinfoW 구조체에 대한 포인터입니다.
4) ppResult : 호스트에 대한 응답 정보를 포함하는 하나 이상의 addrinfoW 구조체의 연결된 목록에 대한 포인터입니다.
5) 반환값 : 성공 시 0을 반환한다.

매개 변수만 보면 뭔가 복잡해 보이는데요. 2번 매개변수와, 3번 매개변수는 저도 솔직히 잘 이해가 되지 않습니다.

그래도 제 목적은 도메인 이름으로 IP주소를 얻는 것이므로 그 방법만 알아보려합니다.

#include <ws2tcpip.h>

int main()
{
	//GetAddrInfo 함수를 쓰기 위한 ADDRINFOW구조체 이 함수를 쓰는 이유는 매개변수로 버퍼를 받고, 유니코드를 지원하기 때문이다.
	//이 구조체는 링크드 리스트 형태로 한 도메인에 설정된 여러 아이피 정보를 물고있다.
	ADDRINFOW* addrInfo;
    //소켓 주소 구조체 선언
    SOCKADDR_IN* sockAddr;
    
    GetAddrInfo(L"www.naver.com", L"0", NULL, &addrInfo)
    //소켓 주소 구조체로 형변환 해서 원하는 도메인에 해당하는 ip를 가지는 소켓 주소 구조체를 얻을 수 있다.
    sockAddr = (SOCKADDR_IN*)(addrInfo->ai_addr);
    
    //GetAddrInfo 함수는 FreeAddrInfo 함수를 호출해서 리소스를 반환해줘야 한다.
	FreeAddrInfo(addrInfo);
}

이런 식으로 쓸 수 있습니다.

참고로 하나의 도메인에는 여러 IP 주소가 할당될 수 있습니다.
그래서 addrInfo 구조체는 리스트의 형태로 여러 addrInfo 구조체가 이어져 있습니다. addrInfo의 멤버에는 ai_next라는 멤버가 있는데 이 멤버로 다음 addrInfo 구조체로 가서 여러 IP에 접근할 수 있습니다.

그리고 잊어서는 안되는 FreeAddrInfo 함수!
반드시 호출해서 메모리 낭비를 막아야 합니다!

2. IP 문자열 -> IN_ADDR 형태

이번에는 IP를 문자열로 바꾸는 방법을 알아봅시다.

흔히 서버 주소를 세팅할 때 IN_ADDR으로 변환해야 하는 경우가 있습니다.
코드를 보시죠

SOCKADDR_IN serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
InetPton(AF_INET, L"192. 168.0.3", &serverAddr.sin_addr);
serverAddr.sin_port = htons(SERVERPORT);

이렇게 InetPton 함수로 IP 문자열을 IN_ADDR 형태로 변환해줄 수 있습니다. 이 때 네트워크 바이트 배열로도 바뀌므로 htonl을 할 필요도 없습니다.

3. IN_ADDR 형태 -> IP 문자열

InetNtop() 함수로 쉽게 할 수 있습니다.

WCHAR serverIPStr[16] = { 0 };
InetNtop(AF_INET, &serverAddr.sin_addr, serverIPStr, 16);

버퍼 하나 준비해주시고 인자로 넘기면 그 버퍼에 IP 문자열이 들어가게 됩니다.

profile
게임 서버 프로그래밍을 공부하고 있습니다.

0개의 댓글