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

C/C++解析char缓冲区存储的IP数据包出错,如何排查?

问题

我有一个存储在char缓冲区中的IP数据包:

char packet[] = "450000CC68C4000001114C4F0A0A0A0AEFFFFFFADEA9076C00B832074D2D534541524348202A20485454502F312E310D0A484F53543A203233392E3235352E3235352E3235303A313930300D0A4D414E3A2022737364703A646973636F766572220D0A4D583A20310D0A53543A2075726E3A6469616C2D6D756C746973637265656E2D6F72673A736572766963653A6469616C3A310D0A555345522D4147454E543A20476F6F676C65204368726F6D652F3130372E302E353330342E313130204D6163204F5320580D0A0D0A";

我尝试使用netinet/ip.h中的ip结构体解析该IP头部,但打印IP长度等信息时出现垃圾值:

#include <netinet/ip.h>

void decodeIPPacket(const char *packet)
{
    struct ip *ipHdr = (struct ip*)(long)packet;
    
    printf("decodeIPPacket:: IP Len: %d", ipHdr->ip_len);
    printf("decodeIPPacket:: srcip: %u", ipHdr->ip_src.s_addr);
    printf("decodeIPPacket:: dstip: %u", ipHdr->ip_dst.s_addr);
}

输出结果:
decodeIPPacket:: IP Len: 12336
decodeIPPacket:: srcip: 808464432
decodeIPPacket:: dstip: 825307440

请问我哪里出错了?

解答
  • 核心错误:你存储的是十六进制字符串,不是原始二进制IP数据包
    你的packet数组里是ASCII格式的十六进制字符(比如"45"是字符'4'和'5'),而struct ip需要直接读取原始二进制字节(比如0x45这个单字节值)。直接把字符串指针强转成struct ip*,会让结构体成员读取到错误的字节组合,自然得到垃圾值。

  • 解决方法

    1. 先把十六进制字符串转成二进制字节流
      遍历字符串,每两个字符对应一个十六进制数,转换成对应的字节值,存入unsigned char缓冲区。示例转换代码:
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <netinet/ip.h>
      #include <arpa/inet.h>
      
      void hexToBin(const char *hexStr, unsigned char *binBuf, size_t bufSize) {
          size_t hexLen = strlen(hexStr);
          if (hexLen % 2 != 0 || bufSize < hexLen/2) {
              return; // 输入格式错误或缓冲区不足
          }
          for (size_t i=0; i<hexLen; i+=2) {
              sscanf(hexStr+i, "%2hhx", &binBuf[i/2]);
          }
      }
      
    2. 处理网络字节序转换
      IP头部的字段(比如ip_len、ip_src.s_addr)都是网络字节序(大端),如果你的主机是小端字节序,必须用ntohs()(转换16位)、ntohl()(转换32位)转换成主机字节序再输出,否则数值会不正确。
    3. 修正解析函数
      用转换后的二进制缓冲区解析,同时优化IP地址的输出格式:
      void decodeIPPacket(const unsigned char *packet) {
          struct ip *ipHdr = (struct ip*)packet;
          printf("decodeIPPacket:: IP Len: %d\n", ntohs(ipHdr->ip_len));
          printf("decodeIPPacket:: srcip: %s\n", inet_ntoa(ipHdr->ip_src));
          printf("decodeIPPacket:: dstip: %s\n", inet_ntoa(ipHdr->ip_dst));
      }
      
    4. 完整调用示例
      int main() {
          char packet[] = "450000CC68C4000001114C4F0A0A0A0AEFFFFFFADEA9076C00B832074D2D534541524348202A20485454502F312E310D0A484F53543A203233392E3235352E3235352E3235303A313930300D0A4D414E3A2022737364703A646973636F766572220D0A4D583A20310D0A53543A2075726E3A6469616C2D6D756C746973637265656E2D6F72673A736572766963653A6469616C3A310D0A555345522D4147454E543A20476F6F676C65204368726F6D652F3130372E302E353330342E313130204D6163204F5320580D0A0D0A";
          size_t binSize = strlen(packet)/2;
          unsigned char *binPacket = malloc(binSize);
          if (binPacket) {
              hexToBin(packet, binPacket, binSize);
              decodeIPPacket(binPacket);
              free(binPacket);
          }
          return 0;
      }
      
      运行后会得到正确的输出:
      decodeIPPacket:: IP Len: 204
      decodeIPPacket:: srcip: 10.10.10.10
      decodeIPPacket:: dstip: 239.255.255.250
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 11:55:20