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

使用C语言向pcap文件写入数据时遇Wireshark截断错误求助

问题:PCAP文件在Wireshark中提示“The captured file appears to have been cut short in the middle of the packet”

你希望在循环中把单个float数据写入PCAP文件,使生成的文件中UDP数据包数量与循环次数一致,但用Wireshark打开文件时出现截断错误,代码如下:

const char* filename = "data.pcap"; 
pcap_t* pcap_handle = pcap_open_dead(DLT_RAW, 65535);
pcap_dumper_t* pcap_file_3 = pcap_dump_open(pcap_handle, filename);

void saveData(float data, pcap_dumper_t* pcap_file_1) {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    
    /* packet header */
    struct pcap_pkthdr packet_header;
    packet_header.ts = tv;
    packet_header.caplen = packet_header.len = sizeof(data) + sizeof(packet_header);

    pcap_dump((u_char*)pcap_file_1, &packet_header, (const u_char*)&data);
}

/* for loop which sends the data to the saveData function */
for(size_t i{0U}; i < 300; i++)
{ 
  CODE TO COMPUTE estimated_val
  saveData(estimated_val, pcap_file_3);
}

pcap_dump_close(pcap_file_3);
pcap_close(pcap_handle);

错误原因分析

  • 数据包长度计算错误:packet_header.caplen和packet_header.len代表的是数据包内容的实际长度(不包含PCAP文件自身的包头pcap_pkthdr),你错误地将pcap_pkthdr的大小加入其中,导致Wireshark认为每个数据包需要更多字节,但实际只写入了4字节的float数据,因此触发截断提示。
  • 链路层类型不匹配:你使用了DLT_RAW类型,该类型要求数据包必须是完整的IP层数据,但你仅写入了一个float值,并非合法的IP包,Wireshark解析时会判定这是不完整的IP数据包,进而报错。

修复方案

方案1:用自定义链路层类型存储原始float数据

如果仅需存储float数据、不需要Wireshark解析为UDP包,可使用DLT_USER类型,Wireshark会将数据视为自定义负载,不会尝试解析为网络协议:

#include <pcap.h>
#include <sys/time.h>

const char* filename = "data.pcap"; 
// 使用DLT_USER作为链路层类型,最大快照长度设为65535
pcap_t* pcap_handle = pcap_open_dead(DLT_USER, 65535);
pcap_dumper_t* pcap_file_3 = pcap_dump_open(pcap_handle, filename);

void saveData(float data, pcap_dumper_t* pcap_file_1) {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    
    struct pcap_pkthdr packet_header;
    packet_header.ts = tv;
    // 数据包内容长度为float的大小(4字节)
    packet_header.caplen = packet_header.len = sizeof(float);

    pcap_dump((u_char*)pcap_file_1, &packet_header, (const u_char*)&data);
}

int main() {
    for(size_t i{0U}; i < 300; i++)
    { 
        float estimated_val = i * 0.1f; // 替换为你的计算逻辑
        saveData(estimated_val, pcap_file_3);
    }

    pcap_dump_close(pcap_file_3);
    pcap_close(pcap_handle);
    return 0;
}

方案2:生成合法UDP数据包(让Wireshark正常识别)

如果需要Wireshark显示为标准UDP包,必须构造完整的以太网帧、IP头和UDP头,再附加float数据:

#include <pcap.h>
#include <sys/time.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <string.h>
#include <arpa/inet.h>

// 以太网帧头部
struct eth_header {
    u_char dst_mac[6];
    u_char src_mac[6];
    u_short eth_type;
};

const char* filename = "data.pcap"; 
// 使用DLT_EN10MB(以太网)作为链路层类型
pcap_t* pcap_handle = pcap_open_dead(DLT_EN10MB, 65535);
pcap_dumper_t* pcap_file_3 = pcap_dump_open(pcap_handle, filename);

void saveUdpPacket(float data, pcap_dumper_t* pcap_file_1) {
    struct timeval tv;
    gettimeofday(&tv, NULL);

    // 构造各层头部与负载
    struct eth_header eth;
    struct ip ip_hdr;
    struct udphdr udp_hdr;
    char payload[sizeof(float)];
    memcpy(payload, &data, sizeof(float));

    // 填充以太网头部
    memset(eth.dst_mac, 0xff, 6); // 广播MAC地址
    memset(eth.src_mac, 0x00, 6); // 示例源MAC地址
    eth.eth_type = htons(0x0800); // IP协议类型

    // 填充IP头部
    ip_hdr.ip_v = 4;
    ip_hdr.ip_hl = 5;
    ip_hdr.ip_tos = 0;
    ip_hdr.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + sizeof(float));
    ip_hdr.ip_id = htons(12345);
    ip_hdr.ip_off = 0;
    ip_hdr.ip_ttl = 64;
    ip_hdr.ip_p = IPPROTO_UDP;
    ip_hdr.ip_src.s_addr = inet_addr("192.168.1.100"); // 示例源IP
    ip_hdr.ip_dst.s_addr = inet_addr("192.168.1.200"); // 示例目的IP
    ip_hdr.ip_sum = 0; // 可由pcap自动计算或手动校验

    // 填充UDP头部
    udp_hdr.source = htons(1234); // 示例源端口
    udp_hdr.dest = htons(5678); // 示例目的端口
    udp_hdr.len = htons(sizeof(struct udphdr) + sizeof(float));
    udp_hdr.check = 0; // 可选,跳过校验和计算

    // 拼接完整数据包
    char packet[sizeof(struct eth_header) + sizeof(struct ip) + sizeof(struct udphdr) + sizeof(float)];
    int offset = 0;
    memcpy(packet + offset, &eth, sizeof(eth));
    offset += sizeof(eth);
    memcpy(packet + offset, &ip_hdr, sizeof(ip_hdr));
    offset += sizeof(ip_hdr);
    memcpy(packet + offset, &udp_hdr, sizeof(udp_hdr));
    offset += sizeof(udp_hdr);
    memcpy(packet + offset, payload, sizeof(float));

    struct pcap_pkthdr packet_header;
    packet_header.ts = tv;
    packet_header.caplen = packet_header.len = sizeof(packet);

    pcap_dump((u_char*)pcap_file_1, &packet_header, (const u_char*)packet);
}

int main() {
    for(size_t i{0U}; i < 300; i++)
    { 
        float estimated_val = i * 0.1f; // 替换为你的计算逻辑
        saveUdpPacket(estimated_val, pcap_file_3);
    }

    pcap_dump_close(pcap_file_3);
    pcap_close(pcap_handle);
    return 0;
}

说明

  • 方案1适合仅需存储数据、无需协议解析的场景,Wireshark会将数据包识别为“User 0”类型,负载即为你的float数据。
  • 方案2会生成标准UDP数据包,Wireshark可正常解析以太网、IP、UDP层信息及负载中的float数据,循环300次将生成300个UDP包。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:26:04