分析
使用netmap工具
安装记录在我的另外一篇博客https://www.cnblogs.com/hunxiaoheibai/p/15802983.html
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/poll.h> #include <arpa/inet.h> #define NETMAP_WITH_LIBS //避免netmap和系统api冲突,用来区分 #include <net/netmap_user.h> #pragma pack(1) //设置一个字节对齐 #define PROTO_IP 0x800 //ip标志 #define PROTO_UDP 17 //udp标志 #define ETH_LENGTH 6 //以太网协议头 struct ethhdr { //目的地址 unsigned char dst[ETH_LENGTH]; //源地址 unsigned char src[ETH_LENGTH]; //类型 unsigned short proto; }; // ip协议封装 struct iphdr { unsigned char version : 4; //版本 unsigned char height : 4; //首部长度。占用半个字节,两个一起占用一个字节 unsigned char tos; //服务类型 unsigned short length; unsigned short id; //标志 unsigned short flag_offset; //偏移 unsigned char ttl; //生存时间 unsigned char proto; //协议 unsigned short check; //检验 unsigned int sip; //源ip unsigned int dip; //目的ip }; // udp协议封装 struct udphdr { unsigned short sport; //源端口 unsigned short dport; //目的端口 unsigned short length; unsigned short check; }; struct udppkt { //转化为内存块,不适用指针 struct ethhdr eh; //14字节 struct iphdr ip; //20字节 struct udphdr udp; //8字节 unsigned char data[0]; //零长数组,0字节 }; int main() { struct nm_desc *nmr = nm_open("netmap:enp0s3", NULL, 0, NULL); if (nmr == NULL) { return 0; } struct pollfd pfd = {0}; pfd.fd = nmr->fd; //操作标识网卡信息,区分多个网卡信息 pfd.events = POLLIN; struct nm_pkthdr h; while (1) { int ret = poll(&pfd, 1, -1); if (ret < 0) continue; if (pfd.revents & POLLIN) { unsigned char *stream = nm_nextpkt(nmr, &h); struct ethhdr *eh = (struct ethhdr *)stream; // 可能有arp协议,加一层ip判断 if (ntohs(eh->proto) == PROTO_IP) { struct udppkt *udp = (struct udppkt *)stream; if (udp->ip.proto == PROTO_UDP) { int udp_length = ntohs(udp->udp.length); udp->data[udp_length - 8] = '\0'; printf("udp->%s\n", udp->data); } } } } }
测试显示发送成功
参考
https://www.bilibili.com/video/BV113411v738