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

Omnet++无线通信数据包发送报错求助:类型转换失败

OMNeT++无线数据包传输类型转换错误解决

错误信息

***check_and_cast(): Cannot cast (omnetpp::cPacket*)Packet to type 'inet::physicallayer::WirelessSignal *' -- in module (inet::physicallayer::Ieee80211Radio) Network1.receiver.wlan[0].radio (id=96), at t=0***

用户代码

Sender模块代码

#include <string.h>
#include <omnetpp.h>

using namespace omnetpp;
using namespace inet;

class Sender : public cSimpleModule
{
  private:
    cMessage *packet;
    simtime_t packetGenerationInterval;
    int packetSize;
    cModule *server;
  protected:
    virtual void initialize() override;
    virtual void handleMessage(cMessage *msg) override;
};

Define_Module(Sender);

void Sender::initialize()
{
    packetGenerationInterval = par("packetGenerationInterval");
    packetSize = par("packetSize");
    packet = new cMessage("Packet");
    server =getModuleByPath("receiver");
    scheduleAt(simTime(), packet);  // Schedule the first packet generation
}

void Sender::handleMessage(cMessage *msg)
{
    if (msg == packet) {
        std::string packetContent = "Packet from Sender1";

        cPacket *newPacket = new cPacket("Packet");
        newPacket->setByteLength(packetSize);
        
        sendDirect(newPacket, server, "radioIn", 0);

        scheduleAt(simTime() + packetGenerationInterval, packet);
    }
}

Receiver模块代码

#include <string.h>
#include <omnetpp.h>

using namespace omnetpp;

class Receiver : public cSimpleModule
{
  protected:
    virtual void handleMessage(cMessage *msg) override;
};

Define_Module(Receiver);

void Receiver::handleMessage(cMessage *msg)
{
    if (msg->isPacket()) {
        EV << "Received packet: " << msg << std::endl;
       }
}

问题原因

直接将cPacket发送到无线电台的radioIn端口是错误的。在INET框架中,IEEE 802.11类型的无线电台仅接收inet::physicallayer::WirelessSignal类型对象,原始cPacket必须经过协议栈(应用层→网络层→链路层→物理层)的封装,最终转换为WirelessSignal才能被电台处理。你的代码绕过了整个协议栈流程,导致类型不匹配。

解决方案

方案1:使用标准协议栈流程(推荐)

调整Sender和Receiver作为无线主机的应用层模块,通过协议栈的上下层端口发送/接收数据包,让INET自动完成数据包到无线信号的封装。

修正后的Sender代码

#include <string.h>
#include <omnetpp.h>
#include <inet/common/INETDefs.h>

using namespace omnetpp;
using namespace inet;

class Sender : public cSimpleModule
{
  private:
    cMessage *packetTimer;
    simtime_t packetGenerationInterval;
    int packetSize;
  protected:
    virtual void initialize() override;
    virtual void handleMessage(cMessage *msg) override;
};

Define_Module(Sender);

void Sender::initialize()
{
    packetGenerationInterval = par("packetGenerationInterval");
    packetSize = par("packetSize");
    packetTimer = new cMessage("packetTimer");
    scheduleAt(simTime(), packetTimer);
}

void Sender::handleMessage(cMessage *msg)
{
    if (msg == packetTimer) {
        cPacket *newPacket = new cPacket("DataPacket");
        newPacket->setByteLength(packetSize);
        
        // 发送到自身out端口,后续连接到无线主机的upperLayerIn
        send(newPacket, "out");

        scheduleAt(simTime() + packetGenerationInterval, packetTimer);
    }
}

修正后的Receiver代码

#include <string.h>
#include <omnetpp.h>
#include <inet/common/INETDefs.h>

using namespace omnetpp;
using namespace inet;

class Receiver : public cSimpleModule
{
  protected:
    virtual void handleMessage(cMessage *msg) override;
};

Define_Module(Receiver);

void Receiver::handleMessage(cMessage *msg)
{
    if (msg->isPacket()) {
        cPacket *packet = check_and_cast<cPacket *>(msg);
        EV << "Received packet: " << packet->getName() << ", size: " << packet->getByteLength() << " bytes" << endl;
        delete packet;
    }
    else {
        delete msg;
    }
}

NED文件调整

将Sender和Receiver作为子模块挂载到无线主机内部,并连接到协议栈端口:

network Network1
{
    submodules:
        senderHost: WirelessHost {
            @display("p=100,100");
            submodules:
                app: Sender;
            connections:
                app.out --> wlan[0].upperLayerIn;
        }
        receiverHost: WirelessHost {
            @display("p=300,100");
            submodules:
                app: Receiver;
            connections:
                wlan[0].upperLayerOut --> app.in;
        }
}

方案2:手动封装WirelessSignal(不推荐)

如果需要直接操作物理层,可以将cPacket封装到WirelessSignal中再发送,但需要手动配置物理层参数:

// 在Sender的handleMessage中替换sendDirect部分
#include <inet/physicallayer/wireless/common/radio/packetlevel/WirelessSignal.h>

// ...

WirelessSignal *signal = new WirelessSignal(newPacket);
// 配置信号参数(如传输功率、调制方式等,需参考INET物理层API)
sendDirect(signal, server, "radioIn", 0);

总结

核心问题是绕过了INET无线协议栈的封装流程,导致原始数据包无法被电台识别。使用标准的应用层→协议栈发送方式是最稳妥的解决方案,无需手动处理物理层信号封装。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 15:07:35