Linux에서 인터페이스의 IP 주소를 가져옵니다.
Linux 상의 인터페이스의 IPv4 주소를 C 코드에서 취득하려면 어떻게 해야 합니까?
예를 들어, eth0에 할당된 IP 주소(있는 경우)를 얻고 싶습니다.
이것을 시험해 보세요.
#include <stdio.h>
#include <unistd.h>
#include <string.h> /* for strncpy */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
int
main()
{
int fd;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
/* I want to get an IPv4 IP address */
ifr.ifr_addr.sa_family = AF_INET;
/* I want IP address attached to "eth0" */
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
ioctl(fd, SIOCGIFADDR, &ifr);
close(fd);
/* display result */
printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
return 0;
}
코드 샘플은 여기서 채취한 것입니다.
ioctl() 메서드 외에 필리핀에서 설명한 getifaddrs()도 사용할 수 있습니다.man 페이지 하단에 예제 프로그램이 있습니다.
wlan0 이라고 하는 특정 인터페이스의 주소(IPv4)를 찾고 있는 경우는, getifaddrs() 를 사용하는 다음의 코드를 사용해 주세요.
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
struct ifaddrs *ifaddr, *ifa;
int family, s;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == -1)
{
perror("getifaddrs");
exit(EXIT_FAILURE);
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
continue;
s=getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if((strcmp(ifa->ifa_name,"wlan0")==0)&&(ifa->ifa_addr->sa_family==AF_INET))
{
if (s != 0)
{
printf("getnameinfo() failed: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
printf("\tInterface : <%s>\n",ifa->ifa_name );
printf("\t Address : <%s>\n", host);
}
}
freeifaddrs(ifaddr);
exit(EXIT_SUCCESS);
}
이더넷의 경우 wlan0을 eth0으로, 로컬루프백의 경우 lo로 대체할 수 있습니다.
사용된 데이터 구조의 구조와 자세한 설명은 여기에서 찾을 수 있다.
C의 링크 리스트에 대한 자세한 내용은 이 페이지를 참고하시기 바랍니다.
최근에도 같은 문제가 발생했는데, 이것이 제가 만든 코드이며, 동작하고 있습니다.네트워크 인터페이스의 이름은, 사용하고 있는 그대로 사용해 주세요( 「eth0」또는 그 외의 경우도 있습니다).
가 아닌가를 확인해야 한다ifconfig
명령어를 사용하여 인터페이스 이름을 취득하고 C에서 사용합니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <linux/if.h>
#include <errno.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void extract_ipaddress()
{
//create an ifreq struct for passing data in and out of ioctl
struct ifreq my_struct;
//declare and define the variable containing the name of the interface
char *interface_name="enp0s3"; //a very frequent interface name is "eth0";
//the ifreq structure should initially contains the name of the interface to be queried. Which should be copied into the ifr_name field.
//Since this is a fixed length buffer, one should ensure that the name does not cause an overrun
size_t interface_name_len=strlen(interface_name);
if(interface_name_len<sizeof(my_struct.ifr_name))
{
memcpy(my_struct.ifr_name,interface_name,interface_name_len);
my_struct.ifr_name[interface_name_len]=0;
}
else
{
perror("Copy name of interface to ifreq struct");
printf("The name you provided for the interface is too long...\n");
}
//provide an open socket descriptor with the address family AF_INET
/* ***************************************************************
* All ioctl call needs a file descriptor to act on. In the case of SIOCGIFADDR this must refer to a socket file descriptor. This socket must be in the address family that you wish to obtain (AF_INET for IPv4)
* ***************************************************************
*/
int file_descriptor=socket(AF_INET, SOCK_DGRAM,0);
if(file_descriptor==-1)
{
perror("Socket file descriptor");
printf("The construction of the socket file descriptor was unsuccessful.\n");
return -1;
}
//invoke ioctl() because the socket file descriptor exists and also the struct 'ifreq' exists
int myioctl_call=ioctl(file_descriptor,SIOCGIFADDR,&my_struct);
if (myioctl_call==-1)
{
perror("ioctl");
printf("Ooops, error when invoking ioctl() system call.\n");
close(file_descriptor);
return -1;
}
close(file_descriptor);
/* **********************************************************************
* If this completes without error , then the hardware address of the interface should have been returned in the 'my_struct.ifr_addr' which is types as struct sockaddr_in.
* ***********************************************************************/
//extract the IP Address (IPv4) from the my_struct.ifr_addr which has the type 'ifreq'
/* *** Cast the returned address to a struct 'sockaddr_in' *** */
struct sockaddr_in * ipaddress= (struct sockaddr_in *)&my_struct.ifr_addr;
/* *** Extract the 'sin_addr' field from the data type (struct) to obtain a struct 'in_addr' *** */
printf("IP Address is %s.\n", inet_ntoa(ipaddress->sin_addr));
}
내 2센트: iOS에서도 동일한 코드가 작동합니다.
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
showIP();
}
void showIP()
{
struct ifaddrs *ifaddr, *ifa;
int family, s;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == -1)
{
perror("getifaddrs");
exit(EXIT_FAILURE);
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
continue;
s=getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if( /*(strcmp(ifa->ifa_name,"wlan0")==0)&&( */ ifa->ifa_addr->sa_family==AF_INET) // )
{
if (s != 0)
{
printf("getnameinfo() failed: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
printf("\tInterface : <%s>\n",ifa->ifa_name );
printf("\t Address : <%s>\n", host);
}
}
freeifaddrs(ifaddr);
}
@end
데이터를 보기 위해 wlan0에 대한 테스트를 삭제했을 뿐입니다.ps "패밀리"를 삭제할 수 있습니다.
바이너리 사이즈에 문제가 없다면 iproute2를 라이브러리로 사용할 수 있습니다.
장점:
- 소켓 레이어 코드를 쓸 필요가 없습니다.
- 네트워크 인터페이스에 대한 정보를 더 많이 또는 더 많이 얻을 수 있습니다.iproute2 툴과 같은 기능.
- 단순한 API 인터페이스.
단점:
- iproute2-as-lib 라이브러리 크기가 큽니다.최대 500kb.
#include <unistd.h>
#if this work you could just do hostname -I on bash
int main(void) {
char *programName = "hostname";
char *arg1 = "-I";
execlp(programName, programName, arg1, NULL, NULL);
return 0;
}
언급URL : https://stackoverflow.com/questions/2283494/get-ip-address-of-an-interface-on-linux
'programing' 카테고리의 다른 글
VueJ - 알 수 없는 로컬 작업 유형: addProductToCart, 글로벌 유형: cart/addProductToCart (0) | 2022.06.18 |
---|---|
Linux에서 getch() & getche()에 해당하는 것은 무엇입니까? (0) | 2022.06.18 |
C 프리프로세서: #warning으로 매크로를 전개합니다. (0) | 2022.06.18 |
C의 함수에 전달된 포인터를 수정하려면 어떻게 해야 하나요? (0) | 2022.06.18 |
Vuex가 복잡한 개체에 반응하지 않음 (0) | 2022.06.18 |