建立一個 UDP Socket,透過 ioctl 系統呼叫搭配 SIOCGIFADDR 指令,從核心查詢指定網卡(如 eth0)的 IPv4 位址結構 sockaddr_in,再用 inet_ntoa 轉為點分十進制字串。
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#define ETH_NAME "eth0"
int main(void) {
int sock;
struct sockaddr_in sin;
struct ifreq ifr;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
perror("socket");
return -1;
}
strncpy(ifr.ifr_name, ETH_NAME, IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) {
perror("ioctl");
close(sock);
return -1;
}
memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
printf("%s: %s\n", ETH_NAME, inet_ntoa(sin.sin_addr));
close(sock);
return 0;
}
gcc get_ip.c -o get_ip
./get_ip
# 輸出範例:eth0: 192.168.1.100
SOCK_DGRAM:UDP Socket 即可,無需建立連線。struct ifreq:網卡請求結構,ifr_name 指定介面名,ifr_addr 回傳地址。SIOCGIFADDR:取得介面 IPv4 位址的 ioctl 指令碼。inet_ntoa:將網路序 in_addr 轉為字串(注意:非執行緒安全,現代代碼建議用 inet_ntop)。使用 getifaddrs()(<ifaddrs.h>)遍歷鏈表,可一次取得所有網卡的 IPv4/IPv6 位址,更適合現代應用。
透過 ioctl + SIOCGIFADDR 是 Linux C 程式獲取指定網卡 IP 的經典做法,理解其結構體佈局與核心交互機制,有助於深入掌握 Linux 網路程式設計。