[NP] IPv4 / IPv6 Address Converter

mlnls·2024년 7월 12일

NP_Project

목록 보기
1/4
post-thumbnail

전체 코드

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <string.h>

int main(int argc, char *argv[]) {
    // 전달받은 명령행 인수 중 첫 번째 인수를 도메인으로 저장
    char *domain = argv[1];
    struct addrinfo *addresses;
    struct addrinfo hints;
    memset(&hints,0,sizeof(hints));
    
    hints.ai_family = AF_UNSPEC;        // IPv4, IPv6 주소 모두를 허용하도록 설정
    hints.ai_socktype = SOCK_STREAM;    // TCP 소켓을 사용하도록 설정

    // getaddrinfo() 함수를 호출하여 도메인 주소 정보를 얻어와 메모리에 저장
    int status = getaddrinfo(domain, NULL, &hints, &addresses);

    struct addrinfo *address = addresses;
    while (address) {
        // ai_addr 멤버가 NULL 인 경우 다음 주소 정보로 이동
        if (address->ai_addr == NULL) {
            address = address->ai_next;
            continue;
        }
        // 현재 주소 정보 체계를 결정
        int family = address->ai_addr->sa_family;
        if (family == AF_INET || family == AF_INET6) {
            // 현재 주소 정보의 주소 체계를 출력
            printf("%s\t", family == AF_INET ? "IPv4" : "IPv6");
            
            // 현재 주소 정보의 IP 주소를 숫자 형태로 출력
            char ap[100];
            const int family_size = family == AF_INET ? sizeof(struct sockaddr_in) 
	            : sizeof(struct sockaddr_in6);
            getnameinfo(address->ai_addr, family_size, ap, sizeof(ap), 0, 0, 
	            NI_NUMERICHOST);
            printf("%s\n", ap);
        }
        // 다음 주소 정보로 이동하여 반복
        address = address->ai_next;
    }
    // 메모리 해제
    freeaddrinfo(addresses);
    return 0;
}

사용자가 입력한 도메인으로 IPv4, IPv6 주소를 출력하는 코드 작성


코드 부연 설명

// 헤더 파일
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <string.h>
  • sys/socket.h : 소켓 관련 함수 및 데이터 형식 포함
  • netdb.h : 네트워크 데이터베이스 관련 함수 포함
  • arpa/inet.h : IPv4 및 IPv6 주소 변환 함수를 포함
  • ifaadrs.h : 네트워크 인터페이스 정보를 가져오는 함수를 포함

// main 함수 & 명령행 인수 처리
int main(int argc, char *argv[]) {
  char *domain = argv[1];
  • 프로그램 실행 시 명령행 인수의 수와 내용을 저장
    그 중 첫 번째 인수를 domain 변수에 저장

// struct addrinfo 및 초기화
struct addrinfo *addresses;
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
    
hints.ai_family = AF_UNSPEC
hints.ai_socktype = SOCK_STREAM;
  • struct addrinfo : 구조체와 초기화를 위한 변수를 선언
    hints 변수를 0으로 초기화

  • AF_UNSPEC : IPv4, IPv6 모두 허용하게 함
  • SOCK_STREAM : 소켓 유형을 TCP 스트림 소켓으로 설정

// getaddrinfo 함수 호출
int status = getaddrinfo(domain, NULL, &hints, &addresses);
  • addresses에 저장된 IP 주소를 반복하며 처리

// IP 주소 및 주소 체계 출력
if (address->ai_addr == NULL) {
  address = address->ai_next;
  continue;
}
int family = address->ai_addr->sa_family;
if (family == AF_INET || family == AF_INET6) {
	...
}
address = address->ai_next;
  • 각 주소 정보가 유호한지 확인 후, 유효한 경우 주소 체계와 IP 주소 출력
    → IPv4, IPv6 인지 확인한 후, 해당 주소 출력

// IP 주소 출력
char ap[100];
const int family_size = family == AF_INET ? sizeof(struct sockaddr_in) 
    : sizeof(struct sockaddr_in6);
getnameinfo(address->ai_addr, family_size, ap, sizeof(ap), 0, 0, NI_NUMERICHOST);
printf("%s\t%s\n", family == AF_INET ? "IPv4" : "IPv6", ap);
  • getnameinfo : 주소를 숫자 형태의 IP 주소로 변환 및 출력

// 메모리 해제
freeaddrinfo(addresses);
  • IP 주소 정보를 저장한 메모리를 해제
profile
@mlnl_s

0개의 댓글