2010-01-07 24 views
14

C 언어를 사용하여 로컬 컴퓨터의 모든 IP 주소를 표시해야합니다. 어떻게 할 수 있습니까?C 프로그램에서 호스트의 IP 주소를 출력하려면 어떻게합니까?

+15

'puts ("127.0.0.1");'농담 :) – pmg

+2

모든 IP 주소는 무엇입니까? 컴퓨터가 할당 된 IP 주소? 네트워크의 IP 주소는 무엇입니까? 또한, 어떤 플랫폼에서 작업하고 있습니까? C 언어 자체는 IP에 대해 아무 것도 모른다. 운영 체제 호출을해야하며 운영 체제 호출이 다를 수 있습니다. –

+6

태그가 "linux"입니다. –

답변

13
#include <stdio.h> 
#include <stropts.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <linux/netdevice.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <unistd.h> 

int print_addresses(const int domain) 
{ 
    int s; 
    struct ifconf ifconf; 
    struct ifreq ifr[50]; 
    int ifs; 
    int i; 

    s = socket(domain, SOCK_STREAM, 0); 
    if (s < 0) { 
    perror("socket"); 
    return 0; 
    } 

    ifconf.ifc_buf = (char *) ifr; 
    ifconf.ifc_len = sizeof ifr; 

    if (ioctl(s, SIOCGIFCONF, &ifconf) == -1) { 
    perror("ioctl"); 
    return 0; 
    } 

    ifs = ifconf.ifc_len/sizeof(ifr[0]); 
    printf("interfaces = %d:\n", ifs); 
    for (i = 0; i < ifs; i++) { 
    char ip[INET_ADDRSTRLEN]; 
    struct sockaddr_in *s_in = (struct sockaddr_in *) &ifr[i].ifr_addr; 

    if (!inet_ntop(domain, &s_in->sin_addr, ip, sizeof(ip))) { 
     perror("inet_ntop"); 
     return 0; 
    } 

    printf("%s - %s\n", ifr[i].ifr_name, ip); 
    } 

    close(s); 

    return 1; 
} 

int main(int argc, char *argv[]) 
{ 
    int domains[] = { AF_INET, AF_INET6 }; 
    int i; 

    for (i = 0; i < sizeof(domains)/sizeof(domains[0]); i++) 
    if (!print_addresses(domains[i])) 
     return 1; 

    return 0; 
} 
+0

모든 IP 주소를 기본 게이트웨이의 IP 주소와 비교하는 것 외에 어떤 인터페이스가 인터넷 연결을위한 "기본"인지 알아내는 가장 좋은 방법은 무엇입니까? – daisy

+0

@ warl0ck 일반적인 경우에 까다로울 수 있습니다. 너 자신의 스택 오버플로에 대한 별도의 질문으로 재미있을 것이다. –

+2

IPv6 주소로는 작동하지 않습니다. – drizzt

3

아직 완전한 해결책은 아니지만, /proc/net을 살펴보십시오! 이름으로

  • dev 목록 사용 가능한 인터페이스 장치,
  • route 목록 어떤 경로 ipv6_route처럼, 실제 라우팅 테이블에
  • arp 목록 장치 (로컬 호스트 포함되지 않습니다).

다른 솔루션과 같이 첨단 기술은 아니지만 간단한 파일 읽기로 수행 할 수 있습니다. 하지만 리눅스는 특별하다.

-3
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/wait.h> 

/* 
* Who sez? 
* http://blog.stackoverflow.com/2010/01/stack-overflow-where-we-hate-fun/ 
*/ 
int main(int argc, char *argv[]) 
{ 
    int status; 
    const char * const cmd = /* die from END is too chatty */ 
    "/sbin/ifconfig -a | \ 
    perl -lne \ 
     'print $1 if /inet6? addr:\\s*(\\S+)/; \ 
     END { $. > 0 or \ 
       warn(\"no output from ifconfig\\n\"), \ 
       exit 1; }'"; 

    status = system(cmd); 
    if (status < 0) { 
    perror("system"); 
    return 1; 
    } 
    else if (status != 0) { 
    const char *extra; 
    status = WEXITSTATUS(status); 
    extra = status == 127 ? " (is /bin/sh ok?)" : ""; 
    fprintf(stderr, "%s: command failed with status %d%s\n", 
      argv[0], status, extra); 
    } 

    return 0; 
} 
+2

해결했다 ... 그 음입니다 .. 속임수 : 피. 그리고 완전히 이식성이 없습니다. – Macha

+3

-1 높은 언어와 다른 유틸리티에 대한 래퍼가 되려고합니다. –

+0

@Macha 어떤 리눅스 배포판이 perl과 함께 제공되지 않습니까? 나는 또한 all-C 답을 주었다. 허용 된 답변보다 간결하고 유지 보수성이 뛰어난 http://blog.stackoverflow.com/2010/01/stack-overflow-where-we-hate-fun/ –

4

/sbin/ifconfig/의 소식통을 속여보고는 어때요? 다른 거인의 어깨에 서 아무 문제 없습니다 ...

+0

죄송합니다! 보이는 것처럼 그것은 주석을 삭제하지 않았다 ... ... – user2284570

-2
 
$ sudo ifconfig | grep 'inet addr' | cut -d':' -f2 | cut -d' ' -f1 
213.xx.xxx.xx 
192.168.xx.x 
127.0.0.1 

그리고 당신은 넣을 수 popen()로 :

/* not tested */ 
ph = popen("sudo ifconfig | grep 'inet addr' | cut -d':' -f2 | cut -d' ' -f1", "r"); 
while (fgets(buf, sizeof buf, ph)) { 
    /* ip address, in nul-terminated string format, is in `buf` */ 
} 
pclose(ph); 
+2

C 코드에서 쉘 명령을 사용하는 경우 -1. IMO에게 권고해서는 안됩니다. 실제 언어와 시스템/라이브러리 호출을 사용하는 솔루션이 훨씬 좋습니다. 특히 이런 초급 질문입니다. –

2

당신은 POSIX 기능 getaddrinfo() 필요 - 그것은 모든 IP 주소의 목록을 연결 반환합니다.

자세한 내용과 예는 man getaddrinfo을 참조하십시오.

9

귀하의 질문이 부정확 할 수 있지만 왜 모든 사람들이 귀하의 쵸콜릿을 부러 뜨릴 지 확신하지 못합니다.

나는 당신이 원할 경우 어쩌면 getifaddrs이냐고 묻고있다. 맨 페이지에는 약간의 예제 프로그램이 있습니다.

ioctl()과 함께 SIOCGIFCONF 옵션을 사용하여 유사한 정보를 얻을 수도 있습니다. here과 웹에 몇 가지 샘플 코드가 있습니다.

이 유사하거나 유사한 용어를 검색하는 경우 이전에 다양한 형식으로이 질문을 물어볼 수 있습니다. 너는 조금 주위를 파다.

또한 NAT를 사용하는 경우 NAT가 네트워크의 공용 IP를 제공하지 않습니다.

7

나는 C에서 그것을 할 또 다른 방법을 말하고 싶다 .... 거기에 쉘에서 그것을 할 수있는 많은 방법이있다, 요점은 무엇입니까?

#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <net/if.h> 

#include <errno.h> 
#include <ifaddrs.h> 
#include <netinet/in.h> 
#include <stdio.h> 
#include <stdlib.h> 


void show_address_info(struct ifaddrs *ifa){ 
    struct sockaddr_in *s4; 
    struct sockaddr_in6 *s6; 
    /* ipv6 addresses have to fit in this buffer */ 
    char buf[64]; 

    if (AF_INET == ifa->ifa_addr->sa_family){ 
    s4 = (struct sockaddr_in *)(ifa->ifa_addr); 
    if (NULL == inet_ntop(ifa->ifa_addr->sa_family, (void *)&(s4->sin_addr), buf, sizeof(buf))){ 
     printf("%s: inet_ntop failed!\n", ifa->ifa_name); 
    } else { 
     printf("IPv4 addr %s: %s\n", ifa->ifa_name, buf); 
    } 
    } 
    else if (AF_INET6 == ifa->ifa_addr->sa_family) { 
    s6 = (struct sockaddr_in6 *)(ifa->ifa_addr); 
    if (NULL == inet_ntop(ifa->ifa_addr->sa_family, (void *)&(s6->sin6_addr), buf, sizeof(buf))) { 
     printf("%s: inet_ntop failed!\n", ifa->ifa_name); 
    } else { 
     printf("IPv6 addr %s: %s\n", ifa->ifa_name, buf); 
     } 
    } 

} 


int main(int argc, char **argv){ 
    struct ifaddrs *myaddrs, *ifa; 
    int status; 

    status = getifaddrs(&myaddrs); 
    if (status != 0){ 
    perror("getifaddrs failed!"); 
    exit(1); 
    } 

    for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next){ 
    if (NULL == ifa->ifa_addr){ 
     continue; 
    } 
    if ((ifa->ifa_flags & IFF_UP) == 0) { 
     continue; 
    } 
    show_address_info(ifa); 
    } 
    freeifaddrs(myaddrs); 
    return 0; 
} 
+0

공유 라이브러리 내부와 같이 많은 환경에서 쉘을 생성하는 것은 옵션이 아닙니다. fork + exec를 사용하면 라이브러리가 링크 된 프로세스에 대해 atexit 처리기가 실행될 수 있습니다. 이는 재앙이 될 수 있습니다. 또한 이러한 셸 유틸리티가 어떻게 구현되어 있다고 생각하십니까? 그들은 C로 구현됩니다. – cmccabe

관련 문제