When doing Linux
network programming, it is often necessary to obtain the local machine IP
address. In addition to the regular reading of configuration files, this article lists several commonly used programming methods known to individuals for reference only. Please point out if there are any errors.
Method 1: Use ioctl() to obtain the local IP address
Linux
Below you can use ioctl()
functions and structures struct ifreq
and structures struct ifconf
to get various information about the network interface. The specific process is to ictol
obtain the information of all local interfaces and save them in ifconf
the structure, and then extract ifreq
the interface information represented by each from it.
If IP
the address of this machine is bound to the first network card, you only need to specify the name of the network card, and you can get it without obtaining the information of all network cards. See the following function:
int get_localip(const char * eth_name, char *local_ip_addr)
{
int ret = -1;
register int fd;
struct ifreq ifr;
if (local_ip_addr == NULL || eth_name == NULL)
{
return ret;
}
if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) > 0)
{
strcpy(ifr.ifr_name, eth_name);
if (!(ioctl(fd, SIOCGIFADDR, &ifr)))
{
ret = 0;
strcpy(local_ip_addr, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
}
}
if (fd > 0)
{
close(fd);
}
return ret;
}
If you want to obtain all network interface information, the sample code is as follows:
#include <stdio.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
int get_localip(const char * eth_name, char *local_ip_addr)
{
int ret = -1;
register int fd, intrface;
struct ifreq ifr[32];
struct ifconf ifc;
if (local_ip_addr == NULL || eth_name == NULL)
{
return ret;
}
if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) > 0)
{
ifc.ifc_len = sizeof ifr;
ifc.ifc_buf = (caddr_t)ifr;
if (!ioctl(fd, SIOCGIFCONF, (char*)&ifc)) //获取所有接口信息
{
intrface = ifc.ifc_len / sizeof(struct ifreq);
while (intrface-- > 0)
{
//Get IP Address
if (!(ioctl(fd, SIOCGIFADDR, (char*)&ifr[intrface])))
{
if(strcmp(eth_name, ifr[intrface].ifr_name) == 0)
{
ret = 0;
sprintf(local_ip_addr, "%s", inet_ntoa(((struct sockaddr_in*)(&ifr[intrface].ifr_addr))->sin_addr));
break;
}
}
}
}
}
if (fd > 0)
{
close(fd);
}
return ret;
}
int main(int argc, const char **argv)
{
int ret;
char local_ip[20] = {
0};
ret = get_localip("eth0", local_ip);
if (ret == 0)
{
printf("local ip:%s\n", local_ip);
}
else
{
printf("get local ip failure\n");
}
return 0;
}
Method 2: getsockname() to obtain the local IP address
getsockname()
Used to get the local address of a bound or connected socket. If a socket is INADDR_ANY
bound with , that is to say, the socket can use the address of any host, at this time unless calling connect()
or accept()
to connect, otherwise getsockname()
will not return IP
any information about the host address.
Sample code:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 80
#define SERVER_IP "192.168.10.31"
int main(int argc, const char **argv)
{
int ret = -1;
socklen_t len;
char buf[30] = {
0};
struct sockaddr_in server_addr, local_addr;
int fd = socket(AF_INET, SOCK_STREAM, 0);
//int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd <= 0)
{
printf("fail to creat socket\n");
return -1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
if(connect(fd, (struct sockaddr*)&server_addr, sizeof(server_addr))<0)
{
printf("connect error!!!\n");
goto end;
}
len = sizeof(local_addr);
memset(&local_addr, 0, sizeof(local_addr));
ret = getsockname(fd, (struct sockaddr*)&local_addr, &len);
if (ret == 0)
{
printf("local ip is %s, local port is %d\n", inet_ntop(AF_INET, &local_addr.sin_addr, buf, sizeof(buf)), ntohs(local_addr.sin_port));
}
else
{
printf("getsockname failed, error=%d\n", errno);
}
end:
if (fd)
{
close(fd);
}
return ret;
}
Method 3: getaddrinfo() to get the local IP address
getaddrinfo()
It can complete the mapping from the host name and service name to the address in the network host, but generally it cannot be used to obtain the local IP
address. When it is used to obtain the local IP
address, it usually returns 127.0.0.1
the local loopback address, and this function only supports it IPv4
.
Sample code:
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
// 获取本地IP时,一般都是127.0.0.1
int main(int argc, const char **argv)
{
int ret;
char host_name[128] = {
0};
struct addrinfo *res, *cur;
struct sockaddr_in *addr;
if (gethostname(host_name, sizeof(host_name)) < 0)
{
printf("gethostname error\n");
return -1;
}
ret = getaddrinfo(host_name, NULL, NULL, &res);
if (ret != 0)
{
printf("Error: error in getaddrinfo on hostname: %s\n", gai_strerror(ret));
return -1;
}
for(cur = res; cur != NULL; cur = cur->ai_next)
{
if(cur->ai_family == AF_INET)
{
addr = (struct sockaddr_in*)cur->ai_addr;
printf("local ip:%s\n", inet_ntoa(addr->sin_addr));
}
//char host[1024] = {0};
//ret = getnameinfo(cur->ai_addr, cur->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
//if(ret != 0)
//{
// printf("getnameinfo: %s\n", gai_strerror(ret));
//}
//else
//{
// printf("ip: %s\n", host);
//}
}
freeaddrinfo(res);
return 0;
}
Method 4: gethostbyname() to get the local IP address
gethostbyname()
Similar to getaddrinfo()
the function of , it is generally used to obtain the address of the host through the host name or service name, such as the domain name IP
. But IP
when you want to get the local address, you usually get the loopback address 127.0.0.1
.
Sample code:
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
// 获取本地IP时,一般都是127.0.0.1
int main(int argc, const char **argv)
{
int i = 0;
char host_name[128] = {
0};
struct hostent *hptr;
if (gethostname(host_name, sizeof(host_name)) < 0)
{
printf("gethostname error\n");
return -1;
}
if ((hptr=gethostbyname(host_name)) == NULL)
{
printf("gethostbyname error\n");
return -1;
}
while(hptr->h_addr_list[i] != NULL)
{
printf("hostname: %s\n", hptr->h_name);
printf(" ip: %s\n", inet_ntoa(*(struct in_addr*)hptr->h_addr_list[i]));
i++;
}
return 0;
}
Method 5: Obtain the local IP address through getifaddrs()
Code from StackOverflow
: http://stackoverflow.com/questions/212528/linux-c-get-the-ip-address-of-local-computer
INET_ADDRSTRLEN
Here is an explanation of and in the code INET6_ADDRSTRLEN
, the macro variable is defined in netinet/in.h
the header file:
// FILE: netinet/in.h
#define INET_ADDRSTRLEN 16 /* for IPv4 dotted-decimal */
#define INET6_ADDRSTRLEN 46 /* for IPv6 hex string */
Sample code:
#include <stdio.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
int main (int argc, const char * argv[])
{
struct ifaddrs * ifAddrStruct=NULL;
struct ifaddrs * ifa=NULL;
void * tmpAddrPtr=NULL;
getifaddrs(&ifAddrStruct);
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
{
if (!ifa->ifa_addr)
{
continue;
}
if (ifa->ifa_addr->sa_family == AF_INET) // check it is IP4
{
// is a valid IP4 Address
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
}
else if (ifa->ifa_addr->sa_family == AF_INET6) // check it is IP6
{
// is a valid IP6 Address
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
}
}
if (ifAddrStruct!=NULL)
{
freeifaddrs(ifAddrStruct);
}
return 0;
}
Method 6: Get the local IP address by calling ifconfig through popen()
Use popen()
to build a pipeline, one end of the pipeline executes the command ifconfig
, and the other end of the pipeline reads the received data and performs corresponding analysis. This method needs to execute shell
commands and cooperate with regular expressions, which is inefficient and generally not used. And this method is actually more inclined to configuration, the reason is that it is easy to use.
Sample code:
#include <stdio.h>
#include <stdlib.h>
#define ETH_NAME "ens33"
int main(int argc, const char *argv[])
{
FILE *fp;
char buf[256] = {
0};
char command[256] = {
0};
//char *fmt = "ifconfig %s|sed -n '2p'|sed -n 's#^.*dr:##gp'|sed -n 's#B.*$##gp'";
char *fmt = "ifconfig %s|grep 'inet addr'|awk '{ print $2}' | awk -F: '{print $2}'";
snprintf(command, sizeof(command), fmt, ETH_NAME);
if((fp = popen(command, "r")) == NULL)
{
perror("Fail to popen\n");
return -1;
}
while(fgets(buf, sizeof(buf), fp) != NULL)
{
printf("%s", buf);
}
pclose(fp);
return 0;
}
reference article
[1] https://blog.csdn.net/bailyzheng/article/details/7489656
[2] https://blog.csdn.net/k346k346/article/details/48231933
[3] https://blog.csdn.net/zhongmushu/article/details/89944990