ZBLOG

数据封装为以太网帧

在计算机网络中,以太网帧是数据链路层的基本单位。当我们需要将某些数据封装为以太网帧时,我们需要遵循以太网协议的格式规范。以下是如何在 C++ 中手动构造一个以太网帧的步骤和示例代码。

以太网帧结构

一个标准的以太网帧通常包括以下字段:

  1. 目标MAC地址(6字节)
  2. 源MAC地址(6字节)
  3. 类型字段(2字节) - 指定上层协议,比如 IPv4、ARP 等
  4. 有效载荷(46-1500字节) - 实际传输的数据
  5. 循环冗余校验码 (CRC) (4字节)

示例代码

以下是一个简单的 C++ 示例,演示如何创建并发送一个包含自定义数据的以太网帧。

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <unistd.h>

void sendEthernetFrame(const std::string &data, const char *destMac) {
    int sockfd;
    struct sockaddr_ll addr;

    // 创建原始套接字
    sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sockfd < 0) {
        perror("Socket creation failed");
        return;
    }

    // 初始化目标地址结构
    memset(&addr, 0, sizeof(addr));
    addr.sll_family = AF_PACKET;
    addr.sll_protocol = htons(ETH_P_ALL);
    
    // 将目的 MAC 地址转为二进制格式
    sscanf(destMac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
           &addr.sll_addr[0], &addr.sll_addr[1], &addr.sll_addr[2],
           &addr.sll_addr[3], &addr.sll_addr[4], &addr.sll_addr[5]);
    
    addr.sll_halen = ETH_ALEN; // MAC 地址长度

    // 构建以太网帧
    unsigned char frame[1514]; // 1514 字节为最大 Ethernet 帧长度

    // 填充目标 MAC 地址
    memcpy(frame, addr.sll_addr, ETH_ALEN);
    
    // 填充源 MAC 地址,这里假设源 MAC 为 "01:02:03:04:05:06"
    unsigned char srcMac[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
    memcpy(frame + ETH_ALEN, srcMac, ETH_ALEN);

    // 填充类型字段,例如使用 IPv4 类型 (0x0800)
    frame[12] = 0x08;
    frame[13] = 0x00;

    // 填充有效载荷,将实际数据放入有效载荷部分
    size_t dataLength = data.size();
    
	// 确保不会超过最大载荷限制,最小为46字节,最多1500字节。
	if (dataLength > (1500 - ETH_HLEN)) {
	    dataLength = (1500 - ETH_HLEN); 
	}
    
	memcpy(frame + ETH_HLEN, data.c_str(), dataLength);

	// 数据包大小,包括头部和有效载荷
	ssize_t bytesSent = sendto(sockfd, frame, dataLength + ETH_HLEN,
		                       0,(struct sockaddr*)&addr,sizeof(addr));
	
	if(bytesSent < 0){
	    perror("Send error");
	}else{
	    std::cout << "Sent " << bytesSent << " bytes" << std::endl;
	}

	close(sockfd); //关闭套接字
}

int main() {
	std::string payload = "Hello Ethernet Frame!";
	const char* destMac = "ff:ff:ff:ff:ff:ff"; // 广播地址
    
	sendEthernetFrame(payload, destMac);
	return 0;
}

注意事项

  1. 权限问题:发送原始以太网帧需要root权限。在Linux系统上运行此程序时,请使用 sudo

  2. 广播与单播:在这个例子中,我们使用了广播MAC地址(ff:ff:ff:ff:ff:ff),可以根据需要替换为其他目的MAC地址。

  3. 有效载荷大小限制:Ethernet II 帧的有效载荷应在46到1500字节之间。如果要发送的数据小于46个字节,应该填充到46个字节。上述代码确保了这点。

通过以上代码,你可以创建并发送自定义的以太网帧,根据实际应用场景修改数据内容和其他参数。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=6753

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?