자신의 PC의 IP를 알아내야 하는 상황인데...

김영훈의 이미지

지금 네트웍프로그램을 짜고 있습니다. 그런데 프로그램내에서 자신의 PC의 IP를 알아내야 하는 상황인데 어떻게 해야 할지를 모르겠습니다. 책에 보면

struct hostent *gethostbyname(const char *name);

이란 함수가 있는데 인자인 name을 어떻게 써야 할지 모르겠습니다. 용례를 보면 www로 시작하는 인자를 넘겨주는 것 같은데 제 PC에서는 그런 name이 없거든요.

sunyzero의 이미지

hosts 파일에 보면 자신의 호스트명이 나오죠. 그겁니다. 호스트명을 구하기 위해선는 gethostname() 함수를 쓰면 됩니다.

========================================
* The truth will set you free.

맹고이의 이미지

간단하게 만들어 본 것입니다...

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/utsname.h>

char **my_addrs(int *addrtype);

int main() {

        char **pptr;
        char str[16];
        int addrtype;

        if((pptr = my_addrs(&addrtype)) == NULL) {
                printf("my_addrs error\n");
                exit(0);
        }

        for( ; *pptr != NULL; pptr++) {
                printf("my address: %s\n", inet_ntop(addrtype, *pptr, str, sizeof(str)));
        }

        return 0;
}

char **my_addrs(int *addrtype) {
        struct hostent *hptr;
        struct utsname myname;

        if(uname(&myname) < 0)
                return NULL;

        if((hptr = gethostbyname(myname.nodename)) == NULL)
                return NULL;

        *addrtype = hptr->h_addrtype;

        return hptr->h_addr_list;
}
김영훈의 이미지

감사합니다. 많은 도움이 되었습니다. 그러나 지금 제가 쓰는 pc의 네트웍 환경이 케이블 모뎀입니다. 그러므로 pc의 주소가 부팅할 때마다 바뀝니다. 이때 두분이 말씀해주신 방법을 쓰면 hosts의 화일의 내용은 바뀌는게 아니므로 아무 소용이 없게 됩니다. 수동으로 바꾸어 주기 전에는 말이죠.

음..
제 생각에 ifconfig의 실행원리를 알면 쉽게 풀어낼 수 있을 것 같은데요...
혹시 아시는 분 계시는지요?

맹고이의 이미지

김영훈 wrote:
음..
제 생각에 ifconfig의 실행원리를 알면 쉽게 풀어낼 수 있을 것 같은데요...
혹시 아시는 분 계시는지요?

그럼, ioctl함수에 SIOCGIFCONF request를 줘서 해결해 보세요.

# 추가: 예전에 kldp 어딘가에서 봤던 소스입니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 
#include <sys/types.h> 
#include <sys/ioctl.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <stropts.h> 

#if defined(sun) 
#include <sys/sockio.h> 
#endif 

#include <net/if.h> 
#if defined(linux) 
#include <linux/sockios.h> 
#endif 

#define BUFFERSIZE 1024 
const char * localip = "0.0.0.0"; 

const char * myip(){ 
        const int MAX_NIC = 10; 
        struct ifconf ifc; 
        struct ifreq ifr[MAX_NIC]; 

        int s; 
        int nNumIFs; 
        int i; 
        int count; 
        int max=2; 
        static char ip[BUFFERSIZE]; 
        int cmd = SIOCGIFCONF; 

        max++; 

        ifc.ifc_len = sizeof ifr; 
        ifc.ifc_ifcu.ifcu_req = ifr; 

        if((s = socket(AF_INET,SOCK_STREAM,0)) < 0) { 
                perror("socket"); 
                exit(1); 
        } 

#if defined(_AIX) 
        cmd = CSIOCGIFCONF; 
#endif 

        if((s = ioctl(s, cmd, &ifc)) < 0) { 
                perror("ioctl"); 
                exit(1); 
        } 

        nNumIFs = ifc.ifc_len / sizeof (struct ifreq); 
        count = 0; 
        strcpy(ip, localip); 
        for(i = 0; i < nNumIFs; i++) { 
                struct in_addr addr; 
                if(ifc.ifc_ifcu.ifcu_req[i].ifr_ifru.ifru_addr.sa_family != AF_INET) { 
                        continue; 
                } 

                addr = ((struct sockaddr_in *) & ifc.ifc_ifcu.ifcu_req[i].ifr_ifru.ifru_addr)->sin_addr; 
                if(addr.s_addr == htonl(0x7f000001)) { 
                        continue; 
                } 
                strcpy(ip, inet_ntoa(addr)); 
                printf("%s IP: %s\n", ifc.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name, ip); 
        } 
        return ip; 
} 

int main() { 
        printf("One of my IP is %s\n", myip()); 
        return 0; 
} 
firebird의 이미지

하나의 호스트가 여러개의 아이피를 가질 수 있다는 점 때문에 문제가 될 수 있겠군요. 아뭏든 네트워크 인터페이스 eth0의 아이피 어드레스를 얻는 예제 코드를 아래에 첨부합니다.
단, 만들어둔 프로그램에서 일부만 가져온 것이므로 header 참조 문제는 맨페이지를 보고 적당히 넣어주세요.

void GetLocalIP(void)
{
    int                sfd;
    struct ifreq       ifr;
    struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.ifr_addr;
    memset(&ifr, 0, sizeof ifr);
    if (0 > (sfd = socket(AF_INET, SOCK_STREAM, 0)))
    {
        perror("socket()");
        return;
    }
    strcpy(ifr.ifr_name, "eth0");
    sin->sin_family = AF_INET;
    if (0 == ioctl(sfd, SIOCGIFADDR, &ifr))
    {
        IPAddress = inet_ntoa(sin->sin_addr);
    }
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.