在实际的项目运用中,我们往往需要绑定本机的IP和端口号,或者作为服务器需要将自己的IP信息更新至数据库中,便于其他其中通过查询数据库得到地址从而发数据,如果我们把它做成智能的获取本机的IP,这样我们的代码的可移植性就提高了。下面就介绍一种在windows和linux下面可以智能获取我们本机的局域网IP的方法,不妥之处还请大家多多指教。
(1)Windows
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")
int GetLocalIP(char *ip)
{
WSADATA wsaData;
char name[155];
PHOSTENT hostinfo;
if (WSAStartup(MAKEWORD(2, 0), &wsaData) == 0)
{
if (gethostname(name, sizeof(name)) == 0)
{
if ((hostinfo = gethostbyname(name)) != NULL)
{
ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list);
printf("local ip : %s\n", ip);
}
}
WSACleanup();
}
return 1;
}
int main(int argc, char argv[])
{
char getip[64] = { 0 };
GetLocalIP(getip);
return 0;
}
(2)Linux
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include<string.h>
#include <sys/ioctl.h>
#include <linux/if.h>
int GetLocalIP(char *ip)
{
int MAXINTERFACES = 16;
int fd, intrface = 0;
struct ifreq buf[MAXINTERFACES]; ///if.h
struct ifconf ifc; ///if.h
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) //socket.h
{
ifc.ifc_len = sizeof buf;
ifc.ifc_buf = (caddr_t)buf;
if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc)) //ioctl.h
{
intrface = ifc.ifc_len / sizeof (struct ifreq);
while (intrface-- > 0)
{
if (!(ioctl(fd, SIOCGIFADDR, (char *)&buf[intrface])))
{
sprintf(ip, "%s", inet_ntoa(((struct sockaddr_in*)(&buf[intrface].ifr_addr))->sin_addr));
printf("ip:%s\n", ip);
break;
}
}
}
close(fd);
}
return 0;
}
该程序可以直接运行,已经在两个平台中测试验证通过!!!
const char * GetLocalAddr(char *ifaddr, size_t ifaddr_size)
{
char *ifaddr_data = NULL;
#ifdef WIN32
char hostname[155];
PHOSTENT hostinfo;
if (gethostname(hostname, sizeof(hostname)) == 0)
{
if ((hostinfo = gethostbyname(hostname)) != NULL)
{
ifaddr_data = strncpy(ifaddr, inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list), ifaddr_size);
}
}
#else
int MAXINTERFACES = 16;
int fd, intrface = 0;
struct ifreq buf[MAXINTERFACES]; ///if.h
struct ifconf ifc; ///if.h
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) //socket.h
{
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = (caddr_t)buf;
if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc)) //ioctl.h
{
intrface = ifc.ifc_len / sizeof(struct ifreq);
for (int i = 0; i < intrface; i++)
{
struct ifreq * lp_ifc_req = &buf[i];
char if_name[32] = { 0 };
strncpy(if_name, lp_ifc_req->ifr_name, sizeof(if_name));
int if_flag = 0;
ioctl(fd, SIOCGIFFLAGS, lp_ifc_req);
if_flag = lp_ifc_req->ifr_flags;
char if_addr[32] = { 0 };
ioctl(fd, SIOCGIFADDR, lp_ifc_req);
inet_ntop(AF_INET, &(((struct sockaddr_in *)&(lp_ifc_req->ifr_addr))->sin_addr),
if_addr, sizeof(if_addr));
#if 1
printf("%2d: ifr_name=%s, ifr_flags= 0x%x, ifr_addr= %s\n", i, if_name, if_flag,
if_addr);
#endif
#define IFF_NET_RUNNING (IFF_UP | IFF_BROADCAST | IFF_MULTICAST | IFF_RUNNING)
if ((if_flag & IFF_LOOPBACK) == (IFF_LOOPBACK) || (if_flag & IFF_NET_RUNNING) != IFF_NET_RUNNING)
continue;
ifaddr_data = strncpy(ifaddr, if_addr, ifaddr_size);
break;
}
}
close(fd);
}
#endif // WIN32
return ifaddr_data;
}