You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MacOS下C语言(Xcode)获取本机MAC地址及发送ARP请求的技术求助

MacOS下C语言获取本机MAC地址与发送ARP请求的实现方案

我之前在MacOS上用C做Socket编程的时候也遇到过类似的需求,给你分享两个适配MacOS(Xcode环境)的实用实现方案:

一、获取本机MAC地址

MacOS推荐用getifaddrs函数来获取网络接口信息,这个接口比旧的sysctl更稳定通用。下面是完整的实现代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <net/if_dl.h>
#include <arpa/inet.h>

// 获取指定网络接口的MAC地址
void get_local_mac_address(const char* interface_name, unsigned char mac_addr[6]) {
    struct ifaddrs *ifap, *ifa;
    struct sockaddr_dl *sdl;

    if (getifaddrs(&ifap) == -1) {
        perror("getifaddrs调用失败");
        exit(EXIT_FAILURE);
    }

    // 遍历所有网络接口
    for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
        // 匹配指定接口,且是数据链路层地址
        if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK && 
            strcmp(ifa->ifa_name, interface_name) == 0) {
            sdl = (struct sockaddr_dl *)ifa->ifa_addr;
            memcpy(mac_addr, LLADDR(sdl), 6); // 复制MAC地址
            break;
        }
    }

    freeifaddrs(ifap);
}

int main() {
    unsigned char mac[6];
    // 替换为你的实际网络接口名,可用`ifconfig`命令查看(比如en0、en1)
    get_local_mac_address("en0", mac);
    printf("本机MAC地址: %02x:%02x:%02x:%02x:%02x:%02x\n", 
           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    return 0;
}

注意点:

  • 先通过ifconfig命令确认你的活跃网络接口名(比如Wi-Fi通常是en0)
  • Xcode中编译时不需要额外的链接参数,直接运行即可

二、MacOS下发送ARP请求

MacOS发送ARP需要使用原始套接字,且必须以root权限运行。下面是构造ARP请求包并发送的实现:

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

// 导入前面的get_local_mac_address函数
void get_local_mac_address(const char* interface_name, unsigned char mac_addr[6]);

// ARP报文完整结构体(以太网帧头+ARP报文)
struct arp_packet {
    struct ether_header eth_hdr;
    struct ether_arp arp_hdr;
};

// 发送ARP请求
int send_arp_request(int sockfd, const char* interface, 
                     unsigned char* src_mac, struct in_addr src_ip, 
                     struct in_addr target_ip) {
    struct arp_packet arp_pkt;
    struct ifreq ifr;
    struct sockaddr_ll dest_addr;

    memset(&arp_pkt, 0, sizeof(struct arp_packet));

    // 填充以太网帧头
    memset(arp_pkt.eth_hdr.ether_dhost, 0xff, 6); // 目的MAC为广播地址
    memcpy(arp_pkt.eth_hdr.ether_shost, src_mac, 6); // 源MAC为本机MAC
    arp_pkt.eth_hdr.ether_type = htons(ETHERTYPE_ARP); // 帧类型为ARP

    // 填充ARP报文
    arp_pkt.arp_hdr.arp_hrd = htons(ARPHRD_ETHER); // 硬件类型:以太网
    arp_pkt.arp_hdr.arp_pro = htons(ETHERTYPE_IP); // 协议类型:IP
    arp_pkt.arp_hdr.arp_hln = 6; // MAC地址长度
    arp_pkt.arp_hdr.arp_pln = 4; // IP地址长度
    arp_pkt.arp_hdr.arp_op = htons(ARPOP_REQUEST); // 操作类型:ARP请求

    memcpy(arp_pkt.arp_hdr.arp_sha, src_mac, 6); // 源MAC
    memcpy(arp_pkt.arp_hdr.arp_spa, &src_ip.s_addr, 4); // 源IP
    memset(arp_pkt.arp_hdr.arp_tha, 0, 6); // 目的MAC暂填0
    memcpy(arp_pkt.arp_hdr.arp_tpa, &target_ip.s_addr, 4); // 目标IP

    // 获取网络接口索引
    strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);
    if (ioctl(sockfd, SIOCGIFINDEX, &ifr) == -1) {
        perror("获取接口索引失败");
        return -1;
    }

    // 设置发送目标地址(广播)
    memset(&dest_addr, 0, sizeof(struct sockaddr_ll));
    dest_addr.sll_family = AF_PACKET;
    dest_addr.sll_ifindex = ifr.ifr_ifindex;
    dest_addr.sll_halen = ETH_ALEN;
    memset(dest_addr.sll_addr, 0xff, 6);

    // 发送ARP请求
    int bytes_sent = sendto(sockfd, &arp_pkt, sizeof(struct arp_packet), 0, 
                           (struct sockaddr*)&dest_addr, sizeof(dest_addr));
    if (bytes_sent == -1) {
        perror("发送ARP请求失败");
        return -1;
    }

    printf("ARP请求已发送,共发送%d字节\n", bytes_sent);
    return 0;
}

int main() {
    // 创建原始套接字,必须root权限
    int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sockfd == -1) {
        perror("创建原始套接字失败");
        printf("请以root权限运行此程序(sudo ./程序名)\n");
        exit(EXIT_FAILURE);
    }

    unsigned char src_mac[6];
    struct in_addr src_ip, target_ip;

    // 获取本机MAC
    get_local_mac_address("en0", src_mac);
    // 设置本机IP(替换为你的实际IP)
    inet_aton("192.168.1.100", &src_ip);
    // 设置要查询的目标IP(比如网关IP)
    inet_aton("192.168.1.1", &target_ip);

    send_arp_request(sockfd, "en0", src_mac, src_ip, target_ip);

    close(sockfd);
    return 0;
}

注意点:

  • 必须以root权限运行:Xcode中可以通过Product > Scheme > Edit Scheme,在Run的Arguments里勾选Run as root;或者编译后用sudo ./程序名运行
  • 替换代码中的本机IP和目标IP为你实际网络环境中的地址
  • 接口名要和前面获取MAC时的一致

内容的提问来源于stack exchange,提问作者user8379153

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:26:35