linux 下获取本地 ip 的几种方法
1. 调用 getifaddrs
The getifaddrs() function first appeared in glibc 2.3, but before glibc 2.3.3, the implementation supported only IPv4 addresses; IPv6 support was added in glibc 2.3.3. Support of address families other than IPv4 is available only on kernels that support netlink.
int getlocaladdrs(char ip_addrs[][IP_ADDRESS_SIZE], \
const int max_count, int *count)
{
struct ifaddrs *ifc;
struct ifaddrs *ifc1;
*count = 0;
if (0 != getifaddrs(&ifc))
{
logError("file: "__FILE__", line: %d, " \
"call getifaddrs fail, " \
"errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
return errno != 0 ? errno : EMFILE;
}
ifc1 = ifc;
while (NULL != ifc)
{
struct sockaddr *s;
s = ifc->ifa_addr;
if (NULL != s && AF_INET == s->sa_family)
{
if (max_count <= *count)
{
logError("file: "__FILE__", line: %d, "\
"max_count: %d < iterface count: %d", \
__LINE__, max_count, *count);
freeifaddrs(ifc1);
return ENOSPC;
}
if (inet_ntop(AF_INET, &((struct sockaddr_in *)s)-> \
sin_addr, ip_addrs[*count], IP_ADDRESS_SIZE) != NULL)
{
(*count)++;
}
else
{
logWarning("file: "__FILE__", line: %d, " \
"call inet_ntop fail, " \
"errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
}
}
ifc = ifc->ifa_next;
}
freeifaddrs(ifc1);
return *count > 0 ? 0 : ENOENT;
}
2. 调用ioctl
int getlocaladdrs(char ip_addrs[][IP_ADDRESS_SIZE], \
const int max_count, int *count)
{
int s;
struct ifconf ifconf;
struct ifreq ifr[32];
int if_count;
int i;
int result;
*count = 0;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
{
logError("file: "__FILE__", line: %d, " \
"socket create fail, errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
return errno != 0 ? errno : EMFILE;
}
ifconf.ifc_buf = (char *) ifr;
ifconf.ifc_len = sizeof(ifr);
if (ioctl(s, SIOCGIFCONF, &ifconf) < 0)
{
result = errno != 0 ? errno : EMFILE;
logError("file: "__FILE__", line: %d, " \
"call ioctl fail, errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
close(s);
return result;
}
if_count = ifconf.ifc_len / sizeof(ifr[0]);
if (max_count < if_count)
{
logError("file: "__FILE__", line: %d, " \
"max_count: %d < iterface count: %d", \
__LINE__, max_count, if_count);
close(s);
return ENOSPC;
}
for (i = 0; i < if_count; i++)
{
struct sockaddr_in *s_in;
s_in = (struct sockaddr_in *) &ifr[i].ifr_addr;
if (!inet_ntop(AF_INET, &s_in->sin_addr, \
ip_addrs[*count], IP_ADDRESS_SIZE))
{
result = errno != 0 ? errno : EMFILE;
logError("file: "__FILE__", line: %d, " \
"call inet_ntop fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
close(s);
return result;
}
(*count)++;
}
close(s);
return *count > 0 ? 0 : ENOENT;
}
3. 判断一个 ip 是否是本地 ip 的几种方法
- 用该 ip 和指定一个端口号,执行b ind 操作,成功则说明是本地 ip,否则不是。
- 上一种方法的问题在于,如果指定的端口被占用了,那么及时是本地 ip,bind 也会出错。可以做如下修改:bind 时指定 0 端口,让系统给分配一个可用的端口。
- 先用上面提到的获取本地 ip 的两种方法把本地 ip 列表获取到,然后看目标 ip 是否在其中即可。