在NS3中使用PointToPointNetDevice的MacTx TraceSource时如何获取数据包源目IP
解决方案
MacTx trace 回调拿到的 Ptr<const Packet> 本身包含完整数据包结构,你看到的「包头为空」是因为NS3不会主动对trace返回的数据包做头部拆分,需要你手动逐层剥离对应协议的头部提取地址,操作步骤如下:
- 第一步:确认你模拟所用的网络设备类型,不同链路层设备的头部结构不同,需要匹配对应头部类处理:
- 若使用Csma设备:先解析
EthernetHeader - 若使用PointToPoint设备:先解析
PppHeader
- 若使用Csma设备:先解析
- 第二步:剥离链路层头部后,匹配网络层协议类型,剥离对应的网络层头部即可拿到源目IP地址,UDP流量默认走IPv4的话对应
Ipv4Header - 第三步:如果需要传输层端口信息,再继续剥离
UdpHeader即可
注意:处理包头时必须先拷贝原始数据包,直接修改原packet会影响后续网络栈的正常转发,需调用pkt->Copy()生成副本再操作。
示例代码
// 引入需要的头文件 #include "ns3/ipv4-header.h" #include "ns3/udp-header.h" // Csma设备用这个头 // #include "ns3/ethernet-header.h" // PointToPoint设备用这个头 #include "ns3/ppp-header.h" void SinkMethod (Ptr<const Packet> pkt) { // 拷贝原包避免影响网络栈处理 Ptr<Packet> copyPkt = pkt->Copy(); // 以下为PointToPoint设备的处理逻辑,Csma设备替换为EthernetHeader即可 PppHeader pppHdr; copyPkt->RemoveHeader(pppHdr); // 判断网络层为IPv4协议再继续解析 if (pppHdr.GetProtocol() == 0x0021) { Ipv4Header ipv4Hdr; copyPkt->RemoveHeader(ipv4Hdr); // 提取源目IP地址 Ipv4Address srcIp = ipv4Hdr.GetSource(); Ipv4Address dstIp = ipv4Hdr.GetDestination(); // 调试打印示例 std::cout << "源IP:" << srcIp << " 目的IP:" << dstIp << std::endl; // 需要UDP端口的话继续解析传输层头部 if (ipv4Hdr.GetProtocol() == 17) { // UDP的协议号固定为17 UdpHeader udpHdr; copyPkt->RemoveHeader(udpHdr); uint16_t srcPort = udpHdr.GetSourcePort(); uint16_t dstPort = udpHdr.GetDestinationPort(); std::cout << "源端口:" << srcPort << " 目的端口:" << dstPort << std::endl; } } }
如果使用Csma设备,将上述代码中的PppHeader替换为EthernetHeader,同时将IPv4协议的判断值从0x0021改为0x0800即可。
内容的提问来源于stack exchange,提问作者soroush
相关产品推荐
相关产品推荐

