当前位置: 首页 > news >正文

以太网协议(Ethernet)深入解析:从底层原理到实战应用

交换机的核心协议,用于定义数据帧的格式和传输方式。

  • 目录

    1. 以太网基础概念

    2. 以太网帧结构详解

    3. MAC地址系统

    4. 以太网物理层

    5. 交换技术原理

    6. 碰撞域与广播域

    7. 实战:C语言实现以太网帧处理

    8. 实战:构建简单交换机

    9. 以太网安全与攻击防护

    10. 未来发展趋势


    1. 以太网基础概念

    1.1 历史发展
        1973 : 施乐帕洛阿尔托研究中心发明以太网1980 : DEC、Intel、Xerox联合推出DIX以太网标准1983 : IEEE 802.3标准正式发布1995 : 100BASE-T(快速以太网)标准化1998 : 千兆以太网(802.3z)发布2002 : 10千兆以太网(802.3ae)发布2016 : 802.3bs(400GbE)标准发布2022 : 800GbE和1.6TbE开始部署

    1.2 核心特点

    • 介质访问控制:CSMA/CD(载波侦听多路访问/碰撞检测)

    • 拓扑结构:总线型 → 星型(现代)

    • 传输速率:10Mbps → 100Mbps → 1Gbps → 10Gbps → 40Gbps → 100Gbps

    • 传输介质:同轴电缆 → 双绞线(UTP/STP) → 光纤

    1.3 以太网工作模型
    +--------------+     +--------------+
    | 应用层       |     | 应用层       |
    +--------------+     +--------------+
    | 传输层       |     | 传输层       |
    +--------------+     +--------------+
    | 网络层       |     | 网络层       |
    +--------------+     +--------------+
    | 数据链路层   |     | 数据链路层   |
    +--------------+     +--------------+
    | 物理层       |     | 物理层       |
    +------+-------+     +-------+------+|                     |+---------------------+物理介质

    2. 以太网帧结构详解

    2.1 以太网帧格式
    // C语言中的以太网帧结构表示
    
    typedef struct {uint8_t dest_mac[6];    // 目标MAC地址 (6字节)uint8_t src_mac[6];     // 源MAC地址 (6字节)uint16_t ethertype;     // 以太网类型 (2字节)uint8_t payload[1500];  // 负载数据 (46-1500字节)uint32_t crc;           // 帧校验序列 (4字节)
    } EthernetFrame;
  • 2.2 字段说明
    字段长度说明
    前导码7字节10101010...用于同步时钟
    SFD1字节帧起始定界符(10101011)
    目标MAC6字节接收方MAC地址
    源MAC6字节发送方MAC地址
    EtherType2字节上层协议标识(0x0800=IPv4, 0x86DD=IPv6)
    载荷46-1500字节传输的数据
    FCS4字节循环冗余校验(CRC-32)
    2.3 EtherType常用值
    十六进制协议
    0x0800IPv4
    0x0806ARP
    0x86DDIPv6
    0x8100VLAN标记
    0x88CCLLDP
    0x8864PPPoE发现阶段
    0x8863PPPoE会话阶段

    3. MAC地址系统

    3.1 MAC地址格式
    3.2 特殊MAC地址
    MAC地址类型用途
    FF:FF:FF:FF:FF:FF广播地址发送到所有设备
    01:80:C2:00:00:00组播地址STP生成树协议
    01:00:0C:CC:CC:CD组播地址CDP/VTP协议
    00:00:0C:xx:xx:xxCisco设备Cisco默认OUI

    4. 以太网物理层

    4.1 编码技术对比
    标准编码方式特点
    10BASE-T曼彻斯特编码1低→高, 0高→低
    100BASE-TX4B/5B → MLT-3三电平编码
    1000BASE-T4D-PAM5五电平编码
    10GBASE-T16-DPAM复杂调制方案
    4.2 常见以太网标准
    标准速率传输距离介质应用
    10BASE-T10Mbps100mCat3+已淘汰
    100BASE-TX100Mbps100mCat5小型网络
    1000BASE-T1Gbps100mCat5e+主流标准
    10GBASE-T10Gbps55-100mCat6a/Cat7数据中心
    40GBASE-SR440Gbps100m多模光纤骨干网
    100GBASE-SR4100Gbps70m多模光纤数据中心骨干

    5. 交换技术原理

    5.1 交换机工作原理
    5.2 交换方式对比
    交换方式特点延迟错误处理典型应用
    存储转发完整接收帧后处理CRC验证现代交换机
    直通交换读取目标MAC即转发无错误校验高速环境
    无碎片接收64字节后转发过滤碎片过渡方案
    5.3 MAC地址表操作
    // C语言实现简单MAC地址表
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    ​
    #define MAX_ENTRIES 1024
    ​
    typedef struct {uint8_t mac[6];int port;time_t last_seen;
    } MACEntry;
    ​
    MACEntry mac_table[MAX_ENTRIES];
    int entry_count = 0;
    ​
    // 更新或添加MAC条目
    void update_mac_table(uint8_t mac[6], int port) {time_t now = time(NULL);// 检查现有条目for (int i = 0; i < entry_count; i++) {if (memcmp(mac_table[i].mac, mac, 6) == 0) {mac_table[i].port = port;mac_table[i].last_seen = now;return;}}// 添加新条目if (entry_count < MAX_ENTRIES) {memcpy(mac_table[entry_count].mac, mac, 6);mac_table[entry_count].port = port;mac_table[entry_count].last_seen = now;entry_count++;}
    }
    ​
    // 老化机制(删除过时条目)
    void age_mac_table(int max_age) {time_t now = time(NULL);int j = 0;for (int i = 0; i < entry_count; i++) {if (now - mac_table[i].last_seen <= max_age) {if (i != j) {mac_table[j] = mac_table[i];}j++;}}entry_count = j;//未过期的总数
    }
    ​
    // 查找MAC对应的端口
    int find_port_by_mac(uint8_t mac[6]) {for (int i = 0; i < entry_count; i++) {if (memcmp(mac_table[i].mac, mac, 6) == 0) {return mac_table[i].port;}}return -1; // 未找到
    }

    6. 碰撞域与广播域

    6.1 概念对比
    6.2 VLAN技术
     

    7. 实战:C语言实现以太网帧处理

    7.1 原始套接字初始化
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <linux/if_packet.h>
    #include <net/ethernet.h>
    #include <net/if.h>
    #include <arpa/inet.h>// 创建原始套接字
    int create_raw_socket(const char *interface) {int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));if (sockfd < 0) {perror("socket");return -1;}// 获取接口索引struct ifreq ifr;memset(&ifr, 0, sizeof(ifr));strncpy(ifr.ifr_name, interface, IFNAMSIZ);if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) {perror("ioctl(SIOCGIFINDEX)");close(sockfd);return -1;}// 绑定到接口struct sockaddr_ll sll;memset(&sll, 0, sizeof(sll));sll.sll_family = AF_PACKET;sll.sll_ifindex = ifr.ifr_ifindex;sll.sll_protocol = htons(ETH_P_ALL);if (bind(sockfd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {perror("bind");close(sockfd);return -1;}// 设置混杂模式if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) == -1) {perror("ioctl(SIOCGIFFLAGS)");close(sockfd);return -1;}ifr.ifr_flags |= IFF_PROMISC;if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) == -1) {perror("ioctl(SIOCSIFFLAGS)");close(sockfd);return -1;}return sockfd;
    }
    7.2 以太网帧解析器
    #include <linux/if_ether.h>void parse_ethernet_frame(const uint8_t *packet, size_t len) {// 检查最小帧长度if (len < sizeof(struct ethhdr)) {fprintf(stderr, "Frame too small: %zu bytes\n", len);return;}const struct ethhdr *eth_header = (struct ethhdr*)packet;// 打印源MAC和目标MACprintf("Ethernet Header:\n");printf("  Destination: %02x:%02x:%02x:%02x:%02x:%02x\n", eth_header->h_dest[0], eth_header->h_dest[1],eth_header->h_dest[2], eth_header->h_dest[3],eth_header->h_dest[4], eth_header->h_dest[5]);printf("  Source:      %02x:%02x:%02x:%02x:%02x:%02x\n", eth_header->h_source[0], eth_header->h_source[1],eth_header->h_source[2], eth_header->h_source[3],eth_header->h_source[4], eth_header->h_source[5]);// 打印类型/长度uint16_t eth_type = ntohs(eth_header->h_proto);printf("  Type:        0x%04x", eth_type);// 识别常见协议switch(eth_type) {case ETH_P_IP:printf(" (IPv4)\n");parse_ip_packet(packet + sizeof(struct ethhdr), len - sizeof(struct ethhdr));break;case ETH_P_IPV6:printf(" (IPv6)\n");// 解析IPv6包break;case ETH_P_ARP:printf(" (ARP)\n");parse_arp_packet(packet + sizeof(struct ethhdr), len - sizeof(struct ethhdr));break;// 更多协议解析...default:printf(" (Unknown)\n");}
    }// ARP包解析示例
    void parse_arp_packet(const uint8_t *packet, size_t len) {if (len < sizeof(struct arphdr)) {fprintf(stderr, "ARP packet too small: %zu bytes\n", len);return;}struct arphdr *arp_header = (struct arphdr*)packet;printf("ARP Packet:\n");printf("  Hardware Type: %u\n", ntohs(arp_header->ar_hrd));printf("  Protocol Type: 0x%04x\n", ntohs(arp_header->ar_pro));printf("  Operation:     %s\n", (ntohs(arp_header->ar_op) == ARPOP_REQUEST) ? "Request" : (ntohs(arp_header->ar_op) == ARPOP_REPLY) ? "Reply" : "Other");// 解析ARP数据部分...
    }
    7.3 帧发送函数
    #include <linux/if_ether.h>void parse_ethernet_frame(const uint8_t *packet, size_t len) {// 检查最小帧长度if (len < sizeof(struct ethhdr)) {fprintf(stderr, "Frame too small: %zu bytes\n", len);return;}const struct ethhdr *eth_header = (struct ethhdr*)packet;// 打印源MAC和目标MACprintf("Ethernet Header:\n");printf("  Destination: %02x:%02x:%02x:%02x:%02x:%02x\n", eth_header->h_dest[0], eth_header->h_dest[1],eth_header->h_dest[2], eth_header->h_dest[3],eth_header->h_dest[4], eth_header->h_dest[5]);printf("  Source:      %02x:%02x:%02x:%02x:%02x:%02x\n", eth_header->h_source[0], eth_header->h_source[1],eth_header->h_source[2], eth_header->h_source[3],eth_header->h_source[4], eth_header->h_source[5]);// 打印类型/长度uint16_t eth_type = ntohs(eth_header->h_proto);printf("  Type:        0x%04x", eth_type);// 识别常见协议switch(eth_type) {case ETH_P_IP:printf(" (IPv4)\n");parse_ip_packet(packet + sizeof(struct ethhdr), len - sizeof(struct ethhdr));break;case ETH_P_IPV6:printf(" (IPv6)\n");// 解析IPv6包break;case ETH_P_ARP:printf(" (ARP)\n");parse_arp_packet(packet + sizeof(struct ethhdr), len - sizeof(struct ethhdr));break;// 更多协议解析...default:printf(" (Unknown)\n");}
    }// ARP包解析示例
    void parse_arp_packet(const uint8_t *packet, size_t len) {if (len < sizeof(struct arphdr)) {fprintf(stderr, "ARP packet too small: %zu bytes\n", len);return;}struct arphdr *arp_header = (struct arphdr*)packet;printf("ARP Packet:\n");printf("  Hardware Type: %u\n", ntohs(arp_header->ar_hrd));printf("  Protocol Type: 0x%04x\n", ntohs(arp_header->ar_pro));printf("  Operation:     %s\n", (ntohs(arp_header->ar_op) == ARPOP_REQUEST) ? "Request" : (ntohs(arp_header->ar_op) == ARPOP_REPLY) ? "Reply" : "Other");// 解析ARP数据部分...
    }

    8. 实战:构建简单交换机

    8.1 简单交换机架构
    #include <pthread.h>
    #include <sys/epoll.h>#define MAX_PORTS 8
    #define MAX_FDS 10typedef struct {int port_num;char name[IFNAMSIZ];int sockfd;uint8_t mac[6];
    } SwitchPort;typedef struct {SwitchPort ports[MAX_PORTS];int port_count;MACEntry mac_table[MAX_ENTRIES];int running;
    } EthernetSwitch;// 初始化交换机
    int init_switch(EthernetSwitch *sw) {// 创建epoll实例int epoll_fd = epoll_create1(0);if (epoll_fd < 0) {perror("epoll_create1");return -1;}// 添加端口监控...struct epoll_event ev;for (int i = 0; i < sw->port_count; i++) {ev.events = EPOLLIN;ev.data.fd = sw->ports[i].sockfd;if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sw->ports[i].sockfd, &ev) < 0) {perror("epoll_ctl");return -1;}}return epoll_fd;
    }// 交换机主循环
    void switch_main_loop(EthernetSwitch *sw) {int epoll_fd = init_switch(sw);struct epoll_event events[MAX_FDS];while (sw->running) {int nfds = epoll_wait(epoll_fd, events, MAX_FDS, 100); // 100ms超时for (int i = 0; i < nfds; i++) {// 处理接收到的帧process_incoming_frame(sw, events[i].data.fd);}// 每10秒老化MAC地址表static time_t last_aging = 0;time_t now = time(NULL);if (now - last_aging > 10) {age_mac_table(&sw->mac_table, MAC_AGING_TIME);last_aging = now;}}close(epoll_fd);
    }// 帧处理函数
    void process_incoming_frame(EthernetSwitch *sw, int port_fd) {// 找到端口索引int port_index = -1;for (int i = 0; i < sw->port_count; i++) {if (sw->ports[i].sockfd == port_fd) {port_index = i;break;}}if (port_index == -1) return;// 接收帧uint8_t buffer[2048];ssize_t len = recv(port_fd, buffer, sizeof(buffer), 0);if (len <= 0) return;// 解析以太网头部struct ethhdr *eth_header = (struct ethhdr*)buffer;// 更新MAC地址表(源MAC对应此端口)update_mac_table(&sw->mac_table, eth_header->h_source, port_index);// 检查目标MACint dest_port = find_port_by_mac(&sw->mac_table, eth_header->h_dest);// 广播或多播处理if (is_broadcast_mac(eth_header->h_dest) || is_multicast_mac(eth_header->h_dest)) {// 泛洪到所有其他端口for (int i = 0; i < sw->port_count; i++) {if (i != port_index) {send_ethernet_frame(sw->ports[i].sockfd, sw->ports[i].mac,eth_header->h_dest,ntohs(eth_header->h_proto),buffer + sizeof(struct ethhdr),len - sizeof(struct ethhdr));}}}// 已知单播处理else if (dest_port >= 0) {send_ethernet_frame(sw->ports[dest_port].sockfd,sw->ports[dest_port].mac,eth_header->h_dest,ntohs(eth_header->h_proto),buffer + sizeof(struct ethhdr),len - sizeof(struct ethhdr));}// 未知单播处理(泛洪)else {for (int i = 0; i < sw->port_count; i++) {if (i != port_index) {send_ethernet_frame(sw->ports[i].sockfd, sw->ports[i].mac,eth_header->h_dest,ntohs(eth_header->h_proto),buffer + sizeof(struct ethhdr),len - sizeof(struct ethhdr));}}}
    }
    8.2 使用Linux网桥配置
    # 创建网桥
    sudo ip link add name br0 type bridge
    sudo ip link set br0 up# 将端口加入网桥
    sudo ip link set eth0 master br0
    sudo ip link set eth1 master br0# 查看网桥状态
    bridge link show# 配置STP生成树协议
    echo 1 | sudo tee /sys/class/net/br0/bridge/stp_state

    9. 以太网安全与攻击防护

    9.1 常见攻击方式及防护
    攻击类型原理防护措施
    MAC洪泛发送大量虚假MAC耗尽交换机表空间端口安全(MAC数量限制)
    ARP欺骗发送虚假ARP响应劫持流量ARP检测、静态ARP绑定
    VLAN跳跃通过双VLAN标签突破隔离Native VLAN配置
    STP攻击发送恶意BPDU接管网络BPDU Guard、根防护
    MAC欺骗伪造合法MAC地址端口安全、动态ARP检测
    9.2 端口安全实现代码
    // 简单端口安全实现
    typedef struct {uint8_t allowed_macs[MAX_MAC_PER_PORT][6];int mac_count;bool sticky;ViolationAction action;
    } PortSecurity;// 检查端口帧的MAC是否合法
    int check_port_security(PortSecurity *ps, uint8_t *src_mac) {// 学习模式下自动添加if (ps->sticky && ps->mac_count < MAX_MAC_PER_PORT) {memcpy(ps->allowed_macs[ps->mac_count], src_mac, 6);ps->mac_count++;return 0;}// 检查MAC是否在允许列表中for (int i = 0; i < ps->mac_count; i++) {if (memcmp(ps->allowed_macs[i], src_mac, 6) == 0) {return 0;}}// 违规处理handle_security_violation(ps->action);return -1;
    }void handle_security_violation(ViolationAction action) {switch(action) {case ACTION_SHUTDOWN:// 关闭端口break;case ACTION_RESTRICT:// 限制流量break;case ACTION_PROTECT:// 记录日志但允许通过syslog(LOG_WARNING, "MAC violation detected");break;}
    }

    10. 未来发展趋势

    10.1 TSN(时间敏感网络)
    10.2 关键技术演进
    1. 高速以太网:800GbE (2022) → 1.6TbE (2025)

    2. 节能以太网:EEE (802.3az) 空闲时节能90%

    3. PoE发展:802.3bt (90W) 支持更多设备

    4. 单对以太网:10BASE-T1S/T1L (汽车、工业物联网)

    5. 自动化运维:AI驱动的故障预测与优化

    10.3 RDMA与RoCE

    RDMA优势

    • 零拷贝技术:绕过内核直接访问内存

    • 低延迟:低于5μs延迟

    • CPU卸载:网卡处理网络协议栈

相关文章:

  • 智能文档结构化技术的应用,重塑合同管理模式
  • 期末考试复习总结-《ArkTS基础语法(上)》
  • G-Star公益行 | 公益组织入门开源技术,六月北京点燃改变的星火
  • Docker常用命令笔记
  • 【大模型】 使用llama.cpp 进行模型转换和量化
  • 魔兽世界正式服插件与宏-敏锐盗贼实用宏探索(3)-起手奥义【袭】之突如其来
  • 使用 origin -> master 强制覆盖本地 master
  • Python Day47 学习(日志Day16-17复习)
  • Win11无法安装Unity5.5.0f3怎么解决?虚拟机中如何配置?Win7怎么安装最新版VMware Tools?来这里教你完美解决!
  • 函数02 day11
  • 模型参数、模型存储精度、参数与显存
  • python46
  • Code Composer Studio快捷键
  • 101.为AI知识问答寻找朗读合适API
  • 5G+边缘计算推动下的商品详情API低延迟高效率新方案
  • 第十一章 通用定时器(上篇)
  • 工业安全零事故的智能守护者:一体化AI智能安防平台
  • DSP——时钟树讲解
  • qt3d自定义生成mesh图形
  • AISHELL-5 全球首套智能驾舱中文语音交互数据集开源
  • 诸城做网站的公司/热狗seo优化外包
  • 珠宝首饰商城网站建设/域名注册查询阿里云
  • wordpress 古典/淘宝关键词优化软件
  • 国外建站主机/在哪个平台做推广比较好
  • 做地产网站/seo关键词排名在线查询
  • dw和asp.net动态网站开发/网站搭建需要多少钱