如何从C程序输出主机的IP地址?

时间:2022-01-02 23:55:59

I need to display all the IP addresses from my local computer, using the C language. How can this be done?

我需要使用C语言显示本地计算机的所有IP地址。如何才能做到这一点?

8 个解决方案

#1


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;
}

#2


10  

Your question might be imprecise but I am not sure why everyone is breaking your chops.

你的问题可能不精确,但我不确定为什么每个人都在打破你的排骨。

I think you are asking the basics in which case you probably want is getifaddrs. The man page has a little example program.

我想你在询问基本知识,你可能想要的是getifaddrs。手册页有一个示例程序。

You can also get similar info using the SIOCGIFCONF option with ioctl(). There is some sample code on here and the web.

您还可以使用带有ioctl()的SIOCGIFCONF选项获取类似信息。这里和网上有一些示例代码。

If you search around for these and similar terms you will find this question has been asked in various forms before. You have to dig around a bit.

如果您搜索这些和类似的术语,您会发现此问题之前已经以各种形式提出。你必须挖掘一下。

Also note, these will not give you the public facing IP of your network if you are behind NAT.

另请注意,如果您位于NAT后面,这些将不会为您提供面向公众的IP网络。

#3


8  

Another way to do it in C. I do have to say though.... there are so many ways to do it from the shell, what's the point?

用C语言做的另一种方法我不得不说....有很多方法可以从shell中做到这一点,有什么意义呢?

#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;
}

#4


4  

How about you simply cheat and look at the source of /sbin/ifconfig/ ? Nothing wrong with standing on the shoulders of other giants...

你怎么样只是欺骗并查看/ sbin / ifconfig /的来源?站在其他巨人的肩膀上没有错...

#5


3  

Not a complete solution yet, but take a look in /proc/net!

还不是一个完整的解决方案,但请查看/ proc / net!

  • dev lists the available interface devices by name,
  • dev按名称列出可用的接口设备,
  • route lists some routes, as does ipv6_route,
  • route列出了一些路由,ipv6_route和
  • arp lists devices in the actual routing table (does not include localhost).
  • arp列出实际路由表中的设备(不包括localhost)。

Not as high-tech as the other solution, but it can be done with simple file reading. Linux specific, though.

不像其他解决方案那样高科技,但可以通过简单的文件读取来完成。但具体是Linux。

#6


2  

You need POSIX function getaddrinfo() - it returns linked list of all IP addresses.

你需要POSIX函数getaddrinfo() - 它返回所有IP地址的链表。

See man getaddrinfo for details and examples.

有关详细信息和示例,请参阅man getaddrinfo。

#7


-2  

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

And you can put that into popen():

你可以把它放到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);

#8


-3  

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

/*
 * Who sez?
 * http://blog.*.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;
}

#1


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;
}

#2


10  

Your question might be imprecise but I am not sure why everyone is breaking your chops.

你的问题可能不精确,但我不确定为什么每个人都在打破你的排骨。

I think you are asking the basics in which case you probably want is getifaddrs. The man page has a little example program.

我想你在询问基本知识,你可能想要的是getifaddrs。手册页有一个示例程序。

You can also get similar info using the SIOCGIFCONF option with ioctl(). There is some sample code on here and the web.

您还可以使用带有ioctl()的SIOCGIFCONF选项获取类似信息。这里和网上有一些示例代码。

If you search around for these and similar terms you will find this question has been asked in various forms before. You have to dig around a bit.

如果您搜索这些和类似的术语,您会发现此问题之前已经以各种形式提出。你必须挖掘一下。

Also note, these will not give you the public facing IP of your network if you are behind NAT.

另请注意,如果您位于NAT后面,这些将不会为您提供面向公众的IP网络。

#3


8  

Another way to do it in C. I do have to say though.... there are so many ways to do it from the shell, what's the point?

用C语言做的另一种方法我不得不说....有很多方法可以从shell中做到这一点,有什么意义呢?

#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;
}

#4


4  

How about you simply cheat and look at the source of /sbin/ifconfig/ ? Nothing wrong with standing on the shoulders of other giants...

你怎么样只是欺骗并查看/ sbin / ifconfig /的来源?站在其他巨人的肩膀上没有错...

#5


3  

Not a complete solution yet, but take a look in /proc/net!

还不是一个完整的解决方案,但请查看/ proc / net!

  • dev lists the available interface devices by name,
  • dev按名称列出可用的接口设备,
  • route lists some routes, as does ipv6_route,
  • route列出了一些路由,ipv6_route和
  • arp lists devices in the actual routing table (does not include localhost).
  • arp列出实际路由表中的设备(不包括localhost)。

Not as high-tech as the other solution, but it can be done with simple file reading. Linux specific, though.

不像其他解决方案那样高科技,但可以通过简单的文件读取来完成。但具体是Linux。

#6


2  

You need POSIX function getaddrinfo() - it returns linked list of all IP addresses.

你需要POSIX函数getaddrinfo() - 它返回所有IP地址的链表。

See man getaddrinfo for details and examples.

有关详细信息和示例,请参阅man getaddrinfo。

#7


-2  

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

And you can put that into popen():

你可以把它放到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);

#8


-3  

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

/*
 * Who sez?
 * http://blog.*.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;
}