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
相关产品推荐
相关产品推荐

