Several methods for Linux C to obtain the host network card name and IP

  When doing Linuxnetwork programming, it is often necessary to obtain the local machine IPaddress. 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

  LinuxBelow you can use ioctl()functions and structures struct ifreqand structures struct ifconfto get various information about the network interface. The specific process is to ictolobtain the information of all local interfaces and save them in ifconfthe structure, and then extract ifreqthe interface information represented by each from it.

If IPthe 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_ANYbound 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 IPany 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 IPaddress. When it is used to obtain the local IPaddress, it usually returns 127.0.0.1the 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 IPwhen 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_ADDRSTRLENHere is an explanation of and in the code INET6_ADDRSTRLEN , the macro variable is defined in netinet/in.hthe 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 shellcommands 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

Guess you like

Origin blog.csdn.net/qq_36393978/article/details/132082698