首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux 網路程式設計:使用 ioctl 與 socket 獲取本機網卡 IP 位址完整指南

     編輯:關於C語言

一、 核心方法:ioctl + SIOCGIFADDR (單網卡)

適用於已知網卡名稱 (如 eth0) 獲取 IPv4 位址。

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>

int main() {
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 建立 UDP socket
    struct ifreq ifr;
    strcpy(ifr.ifr_name, "eth0"); // 目標網卡名

    if (ioctl(sockfd, SIOCGIFADDR, &ifr) == 0) {
        struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
        printf("IP: %s\n", inet_ntoa(sin->sin_addr));
    } else {
        perror("ioctl");
    }
    close(sockfd);
    return 0;
}

二、 進階方法:ioctl + SIOCGIFCONF (遍歷所有網卡)

獲取系統所有網卡介面資訊,再逐一提取 IP。

struct ifconf ifc;
char buf[512];
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;

ioctl(sockfd, SIOCGIFCONF, &ifc); // 獲取所有介面

struct ifreq *ifr = (struct ifreq*)buf;
int count = ifc.ifc_len / sizeof(struct ifreq);
for (int i = 0; i < count; i++, ifr++) {
    if (ifr->ifr_addr.sa_family == AF_INET) { // 僅 IPv4
        printf("Interface: %s, IP: %s\n",
               ifr->ifr_name,
               inet_ntoa(((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr));
    }
}

三、 關鍵結構體解析

  • struct ifreq:單一介面資訊容器。ifr_name 存介面名,ifr_ifru 聯合體存 IP、廣播、子網掩碼、MAC、MTU 等。
  • struct ifconf:介面列表容器。ifc_len 緩衝區長度,ifc_buf 指向 ifreq 陣列緩衝區。

四、 Windows 平台對應:WSAIoctl / GetAdaptersInfo

Linux 用 ioctl,Windows 需用 WSAIoctl 或 IP Helper API (GetAdaptersAddresses)。
socket() 參數同義:AF_INET (IPv4)、SOCK_DGRAM (UDP)、protocol=0 (自動選協定)。

五、 常見坑點提醒

  1. 緩衝區大小:ifc.ifc_len 需足夠大 (如 1024/4096),否則截斷。
  2. 權限:通常需 root 權限或 CAP_NET_ADMIN。
  3. IPv6:sa_family == AF_INET6 時轉型為 sockaddr_in6。
  4. inet_ntoa 非執行緒安全,多執行緒請用 inet_ntop。

總結

ioctl 配合 SIOCGIFADDR/SIOCGIFCONF 是 Linux 獲取網卡 IP 的標準底層方式。理解 ifreq/ifconf 聯合體結構,掌握單網卡查詢與全介面遍歷兩種模式,即可靈活應對各類網路工具開發需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved