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

OMNeT++/INET中无线链路丢包率及全网丢包总数计算方法问询

如何在OMNeT++/INET中计算无线网络链路丢包率和全网丢包总数

嘿,作为刚上手OMNeT++和INET的新手,你提的这个链路丢包率统计需求非常典型——我来一步步帮你落地实现!首先得确认你的核心公式完全正确:Packet Loss Ratio = TotalLostPackets / SentPackets,而且你明确排除了目的地址不匹配的数据包,这个方向抓得很准。

核心思路拆解

我们需要实现两个核心统计目标:

  1. 每条双向可达链路的丢包率:每个节点要跟踪「发送给特定邻居的数据包数」和「从该邻居成功接收的、目的为本节点的数据包数」,两者的差值就是这条单向链路的丢包数,再除以发送数得到丢包率;双向链路则需要统计两个方向的数值。
  2. 全网丢包总数:汇总所有节点的单向链路丢包数之和即可。

步骤1:为每个节点添加链路统计模块

INET的AdhocHost已经封装了完整的网络、MAC、物理层逻辑,我们不用修改底层代码,只需要给每个主机添加一个自定义的统计模块(比如LossStatsCollector),通过订阅INET的信号来捕获数据包的收发事件。

第一步:修改NED文件

先把自定义统计模块加入到你的网络拓扑中,修改后的NED代码如下:

import inet.networklayer.configurator.ipv4.Ipv4NetworkConfigurator;
import inet.node.inet.AdhocHost;
import inet.physicallayer.ieee80211.packetlevel.Ieee80211ScalarRadioMedium;
import inet.visualizer.contract.IIntegratedVisualizer;
// 导入你的自定义统计模块(替换成你实际的包路径)
import your.module.path.LossStatsCollector;

network Net80211 {
    parameters:
        int numHosts;
        @display("bgb=650,450;bgi=background/terrain");
    submodules:
        visualizer: <default("IntegratedCanvasVisualizer")> like IIntegratedVisualizer if hasVisualizer() {
            parameters:
                @display("p=640,15;is=s");
        }
        configurator: Ipv4NetworkConfigurator {
            parameters:
                @display("p=640,112;is=s");
        }
        radioMedium: Ieee80211ScalarRadioMedium {
            parameters:
                @display("p=638,56;is=s");
        }
        // 全局统计模块,用于汇总全网丢包数
        globalLossStats: GlobalLossStats {
            parameters:
                @display("p=640,200;is=s");
        }
        host[numHosts]: AdhocHost {
            parameters:
                @display("r=,,#707070;p=300,200;is=s");
            submodules:
                lossStats: LossStatsCollector {
                    parameters:
                        @display("p=100,100");
                }
        }
}

第二步:编写统计模块的C++代码

这个模块需要订阅INET的数据包收发信号,记录每个邻居的收发计数,最后计算丢包率并输出结果:

#include <inet/common/INETDefs.h>
#include <inet/common/packet/Packet.h>
#include <inet/networklayer/common/L3Address.h>
#include <inet/networklayer/common/L3AddressTag_m.h>

using namespace inet;

class LossStatsCollector : public cSimpleModule {
protected:
    // 存储<目标地址, 发送数据包数>
    std::map<L3Address, int> sentPacketCounts;
    // 存储<源地址, 成功接收的数据包数(目的为本节点)>
    std::map<L3Address, int> receivedPacketCounts;

    virtual void initialize(int stage) override;
    virtual void receiveSignal(cComponent* source, simsignal_t signalID, cObject* obj, cObject* details) override;
    virtual void finish() override;
};

Define_Module(LossStatsCollector);

void LossStatsCollector::initialize(int stage) {
    cSimpleModule::initialize(stage);
    if (stage == INITSTAGE_APPLICATION_LAYER) {
        // 订阅数据包发送和接收的信号
        subscribe(packetSentToLowerSignal, getParentModule());
        subscribe(packetReceivedFromLowerSignal, getParentModule());
    }
}

void LossStatsCollector::receiveSignal(cComponent* source, simsignal_t signalID, cObject* obj, cObject* details) {
    auto packet = check_and_cast<Packet*>(obj);
    auto l3Tag = packet->findTag<L3AddressInd>();
    if (!l3Tag) return; // 跳过无网络层地址的包

    if (signalID == packetSentToLowerSignal) {
        // 记录发送给目标地址的数据包数
        L3Address destAddr = l3Tag->getDestAddress();
        sentPacketCounts[destAddr]++;
    } else if (signalID == packetReceivedFromLowerSignal) {
        // 只统计目的地址为本节点的数据包
        L3Address selfAddr = getParentModule()->par("ipv4Address").stringValue();
        if (l3Tag->getDestAddress() != selfAddr) return;

        // 记录从源地址接收的数据包数
        L3Address srcAddr = l3Tag->getSrcAddress();
        receivedPacketCounts[srcAddr]++;
    }
}

void LossStatsCollector::finish() {
    cSimpleModule::finish();
    std::string hostName = getParentModule()->getFullName();
    int totalSent = 0, totalReceived = 0;

    // 输出每条单向链路的丢包统计
    for (const auto& entry : sentPacketCounts) {
        L3Address destAddr = entry.first;
        int sent = entry.second;
        int received = receivedPacketCounts.count(destAddr) ? receivedPacketCounts[destAddr] : 0;
        int lost = sent - received;
        double lossRatio = sent > 0 ? static_cast<double>(lost) / sent : 0.0;

        // 输出到仿真日志
        EV_INFO << hostName << " -> " << destAddr.str() 
                << " | 发送: " << sent << " 接收: " << received << " 丢包: " << lost 
                << " 丢包率: " << lossRatio * 100 << "%" << endl;

        // 记录到仿真结果文件
        recordScalar(("LossRatio_" + destAddr.str()).c_str(), lossRatio);
        recordScalar(("LostPackets_" + destAddr.str()).c_str(), lost);

        totalSent += sent;
        totalReceived += received;
    }

    // 计算本节点总丢包数
    int nodeTotalLost = totalSent - totalReceived;
    EV_INFO << hostName << " 总丢包数: " << nodeTotalLost << endl;
    recordScalar("NodeTotalLostPackets", nodeTotalLost);

    // 发送总丢包数给全局统计模块
    cMessage* lossMsg = new cMessage("NodeTotalLost");
    lossMsg->addPar("lostCount") = nodeTotalLost;
    sendDirect(lossMsg, getParentModule()->getParentModule()->getSubmodule("globalLossStats"));
}

步骤2:实现全网丢包总数统计

我们需要一个全局模块来汇总所有节点的丢包数,代码如下:

#include <inet/common/INETDefs.h>

using namespace inet;

class GlobalLossStats : public cSimpleModule {
protected:
    int networkTotalLost = 0;

    virtual void handleMessage(cMessage* msg) override;
    virtual void finish() override;
};

Define_Module(GlobalLossStats);

void GlobalLossStats::handleMessage(cMessage* msg) {
    if (msg->isName("NodeTotalLost")) {
        int nodeLost = msg->par("lostCount").intValue();
        networkTotalLost += nodeLost;
        delete msg;
    }
}

void GlobalLossStats::finish() {
    cSimpleModule::finish();
    EV_INFO << "全网总丢包数: " << networkTotalLost << endl;
    recordScalar("NetworkTotalLostPackets", networkTotalLost);
}

关键注意事项

  • 过滤非目标包:一定要检查接收包的目的地址是否为本节点,避免把转发的数据包误统计为接收成功的包,这会导致丢包率计算错误。
  • 处理除数为0:如果某个节点没有给特定邻居发送过包,丢包率直接设为0,避免出现除以0的运行时错误。
  • 结果持久化:使用recordScalar()函数可以把统计结果写入仿真输出文件(.sca),方便后续用OMNeT++的分析工具或者Excel处理。
  • 信号名称确认:如果使用的是INET最新版本,信号名称可能有细微调整,可以查阅INET的API文档确认具体的信号常量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 18:12:36