본문 바로가기
프로그래밍/C

inet_addr, inet_aton, inet_pton, inet_ntoa, inet_ntop

by eteo 2024. 12. 17.

 

 

 

1. 문자열 형식의 IP 주소를 uint32_t 형식으로 변환하는 함수 :

inet_addr, inet_aton, inet_pton

 

 

- inet_addr

  • 문자열 형식의 IPv4 주소를 uint32_t로 변환.
  • 반환된 값이 네트워크 바이트 순서로 저장됨.
  • Deprecated(더 이상 권장되지 않으며, 향후 버전에서 제거될 가능성이 있으니 사용을 자제해야하는 함수) 이므로 최신 코드에서는 inet_aton 또는 inet_pton을 사용하는 것이 권장됨.
#include <stdio.h>
#include <stdint.h>
#if defined(_WIN32) || defined(_WIN64)
#pragma comment(lib,"ws2_32")
#include <WinSock2.h>
#else
#include <arpa/inet.h>
#endif

int main() {
	const char* ip_str = "192.168.1.1";
	uint32_t ip = inet_addr(ip_str);
	printf("IP 주소: 0x%08X\n", ntohl(ip));

	return 0;
}

 

 

 

 

- inet_aton

  • 문자열 형식의 IPv4 주소를 struct in_addr로 변환. 
  • 변환된 결과는 네트워크 바이트 순서로 저장됨. 
  • inet_addr의 대체 함수로 더 안전하게 사용 가능.
  • 윈도우 운영체제에서는 지원되지 않음.
#include <stdio.h>
#include <arpa/inet.h>

void main() {
    struct in_addr addr;
    inet_aton("192.168.1.1", &addr);
    uint32_t ip = addr.s_addr;
    printf("IP 주소: 0x%08X\n", ntohl(ip));
}

 

 

 

 

 

- inet_pton

  • 문자열을 IPv4 또는 IPv6 주소로 변환.
  • 다목적으로 사용 가능하며, IPv4와 IPv6 모두를 지원하는 표준적인 방법.
  • 결과는 네트워크 바이트 순서로 저장됨.
#include <stdio.h>
#include <stdint.h>
#if defined(_WIN32) || defined(_WIN64)
#pragma comment(lib,"ws2_32")
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#endif

int main() {
	struct in_addr addr;
	inet_pton(AF_INET, "192.168.1.1", &addr);
	uint32_t ip = addr.s_addr;
	printf("IPv4 주소: 0x%08X\n", ntohl(ip));

	const char* ipv6_str = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
	struct in6_addr addr6;

	if (inet_pton(AF_INET6, ipv6_str, &addr6) > 0) {
		printf("IPv6 주소: ");
		for (int i = 0; i < 16; i++) {
			printf("%02x", addr6.s6_addr[i]);
			if (i % 2 == 1 && i < 15) printf(":");
		}
		printf("\n");
	}

	return 0;
}

 

 

 

 

 

2. uint32_t 형식의 IP 주소를 문자열로 변환하는 함수 :

inet_ntoa, inet_ntop

 

 

 

- inet_ntoa

  • struct in_addr의 네트워크 오더 s_addr을 IPv4 문자열로 변환. 
  • 반환된 문자열은 함수가 정의된 소스 파일의 정적 전역 변수에 저장되어 여러 스레드에서 동시에 사용하기에 안전하지 않음. 
  • IPv4 전용.
#include <stdio.h>
#include <stdint.h>
#if defined(_WIN32) || defined(_WIN64)
#pragma comment(lib,"ws2_32")
#include <WinSock2.h>
#else
#include <arpa/inet.h>
#endif

int main() {
	struct in_addr addr;
	addr.s_addr = htonl(0xC0A80101);
	char* ip_str = inet_ntoa(addr);
	printf("IPv4 주소: %s\n", ip_str);

	return 0;
}

 

 

 

- inet_ntop

  • struct in_addr 또는 struct in6_addr의 네트워크 오더 s_addr을 문자열 IP 주소로 변환.
  • IPv4와 IPv6 모두 지원.
  • 변환 결과가 사용자 제공 버퍼에 저장되어 스레드 안전함
#include <stdio.h>
#include <stdint.h>
#if defined(_WIN32) || defined(_WIN64)
#pragma comment(lib,"ws2_32")
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#endif

int main() {
	struct in_addr addr;
	addr.s_addr = htonl(0xC0A80101);
	char ipv4_str[INET_ADDRSTRLEN];
	inet_ntop(AF_INET, &addr, ipv4_str, INET_ADDRSTRLEN);
	printf("IPv4 주소: %s\n", ipv4_str);

	struct in6_addr addr6;
	const char* ipv6_address = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
	inet_pton(AF_INET6, ipv6_address, &addr6);
	char ipv6_str[INET6_ADDRSTRLEN];
	inet_ntop(AF_INET6, &addr6, ipv6_str, INET6_ADDRSTRLEN);
	printf("IPv6 주소: %s\n", ipv6_str);

	return 0;
}

 

 

 

 

 

 

 

 

 

 

3. 네트워크 관련 헤더 파일 또는 스탠다드 라이브러리를 사용하지 않고 uint32_t 와 문자열 형식의 IP 주소를 변환하기

 

- 문자열 IP 주소를 받아서 호스트 바이트 순서의 uint32_t 값으로 변환

#include <stdio.h>
#include <stdint.h>

uint32_t ip_to_uint32(const char* ip) {
	uint32_t result = 0;
	uint32_t octet = 0;
	int dot_count = 0;

	while (*ip) {

		if (*ip >= '0' && *ip <= '9') {
			octet = octet * 10 + (*ip - '0');

			if (octet > 255) {
				return 0;
			}
		}
		else if (*ip == '.') {
			result = (result << 8) | octet;
			octet = 0;
			dot_count++;

			if (dot_count > 3) {
				return 0;
			}
		}
		else {
			return 0;
		}
		ip++;
	}

	result = (result << 8) | octet;

	if (dot_count != 3) {
		return 0;
	}

	return result;
}

int main() {
	char ip_str[16] = "192.168.0.10";

	uint32_t ip_uint32 = ip_to_uint32(ip_str);
	printf("IP 주소: 0x%08X\n", ip_uint32);

	return 0;
}

 

 

 

- 호스트 바이트 순서의 uint32_t 값을 받아서 문자열 IP 주소로 변환

#include <stdio.h>
#include <stdint.h>

void uint32_to_ip_string(uint32_t ip, char *buffer) {
    uint8_t octets[4];
    
    octets[0] = (ip >> 24) & 0xFF;
    octets[1] = (ip >> 16) & 0xFF;
    octets[2] = (ip >> 8) & 0xFF;
    octets[3] = ip & 0xFF;

    int index = 0;

    for (int i = 0; i < 4; i++) {
        uint8_t value = octets[i];
        int digits[3];
        int digit_count = 0;
        
        if(value == 0) {
            buffer[index++] = '0';
        }
        else {
            while (value > 0) {
                digits[digit_count++] = value % 10;
                value /= 10;
            }
    
            while (digit_count > 0) {
                buffer[index++] = '0' + digits[--digit_count];
            }
        }

        if (i < 3) {
            buffer[index++] = '.';
        }
    }

    buffer[index] = '\0';
}

int main() {

    uint32_t ip = 0xC0A80101;
    char buffer[16];
    
    uint32_to_ip_string(ip, buffer);

    printf("IP 주소 : %s\n", buffer);
    return 0;
}