接收封装为以太网帧的数据通常涉及使用原始套接字(raw sockets)来捕获网络层传输的所有数据包。下面是一个简单的示例,演示如何在 C++ 中接收以太网帧。
示例代码
以下代码展示了如何创建一个原始套接字并监听通过网络接口接收到的以太网帧:
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <unistd.h>
void receiveEthernetFrame() {
int sockfd;
unsigned char buffer[1514]; // 1514 字节为最大 Ethernet 帧长度
// 创建原始套接字
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
perror("Socket creation failed");
return;
}
while (true) {
ssize_t bytesReceived = recv(sockfd, buffer, sizeof(buffer), 0);
if (bytesReceived < 0) {
perror("Receive error");
break;
}
struct ethhdr *ethHeader = (struct ethhdr *)buffer;
// 打印源和目标 MAC 地址
std::cout << "Source MAC: " << ether_ntoa((struct ether_addr*)ethHeader->h_source) << std::endl;
std::cout << "Destination MAC: " << ether_ntoa((struct ether_addr*)ethHeader->h_dest) << std::endl;
// 打印有效载荷内容(假设这里只处理前46个字节)
std::cout << "Payload: ";
for (int i = 0; i < bytesReceived - ETH_HLEN; ++i) {
std::cout << buffer[ETH_HLEN + i]; // 有效载荷从ETH_HLEN开始
}
std::cout << std::endl;
}
close(sockfd); //关闭套接字
}
int main() {
receiveEthernetFrame();
return 0;
}
注意事项
权限问题:像发送以太网帧一样,使用原始套接字来捕获数据包也需要 root 权限。在Linux系统上运行此程序时,请使用
sudo
。数据解析:在实际应用中,您可能需要根据类型字段(Ethertype)解析不同协议的数据。例如,如果你知道你的有效载荷是IPv4报文,可以进一步解析这些数据。
无限循环:上面的代码会持续运行并打印所有收到的以太网帧。如果你想要在特定条件下退出,需要添加适当的退出机制(例如,通过信号处理)。
性能考虑:在高流量环境下,这种方法可能导致大量输出,因此应考虑过滤或仅选择感兴趣的数据进行处理。
数据结构大小:请确保处理足够大缓冲区,以容纳完整的以太网帧和其他可能包含的头信息。在一般情况下,最大以太网帧大小为1500字节,加上14字节头部,总共1514字节。
以上就是一个基本的框架,用于接受封装为以太网帧的数据,你可以根据需求修改和扩展它。
内容由零声教学AI助手提供,问题来源于学员提问