VEINs/OMNeT++中基于定时器的消息广播机制实现问题
解决方案
1. 先在类中添加成员变量存储待广播消息
首先在MyApp.h的类定义里,新增一个成员变量用来保存待广播的消息副本,避免局部变量丢失:
class MyApp : public BaseWaveApplLayer { // 其他已有成员... cMessage* RstValueEvt; infoMsg* pendingBroadcastMsg = nullptr; // 新增:存储待广播的消息副本 };
2. 修改onWSM函数的消息处理逻辑
修正消息复制的错误,把副本存到成员变量里,同时处理定时器取消时的内存清理:
void MyApp::onWSM(BaseFrame1609_4* frame) { infoMsg* wsm = check_and_cast<infoMsg*>(frame); // 处理目标为自身的初始消息 if (wsm->getRecipient() == myId) { // 如果定时器已调度,取消并清理旧的待广播消息 if (RstValueEvt->isScheduled()) { cancelEvent(RstValueEvt); if (pendingBroadcastMsg != nullptr) { delete pendingBroadcastMsg; pendingBroadcastMsg = nullptr; } } else { // 计算定时器时长(根据你实现的距离逻辑算出timer值) scheduleAt(simTime() + timer, RstValueEvt); // 正确复制消息:调用dup()并转为infoMsg*类型 pendingBroadcastMsg = check_and_cast<infoMsg*>(wsm->dup()); // 设置消息为广播模式(比如把收件人设为广播标识,例如-1) pendingBroadcastMsg->setRecipient(-1); } } // 处理收到其他节点的广播消息:取消自身定时器并清理副本 else if (wsm->getRecipient() == -1) { // 这里假设-1为广播标识 if (RstValueEvt->isScheduled()) { cancelEvent(RstValueEvt); if (pendingBroadcastMsg != nullptr) { delete pendingBroadcastMsg; pendingBroadcastMsg = nullptr; } } } }
注意:
dup()是OMNeT++中cMessage的成员函数,必须通过指针调用;设置广播收件人标识是为了让后续消息能被全网节点识别接收。
3. 实现handleSelfMsg函数处理定时器到期事件
在handleSelfMsg中监听定时器事件,到期后广播消息并清理资源:
void MyApp::handleSelfMsg(cMessage* msg) { if (msg == RstValueEvt) { // 检查是否有待广播的消息副本 if (pendingBroadcastMsg != nullptr) { // 调用VEINs的sendDown函数广播消息 sendDown(pendingBroadcastMsg); // sendDown会接管消息所有权,无需手动delete,只需置空指针 pendingBroadcastMsg = nullptr; } } else { // 处理其他自定义自消息(如果有) BaseWaveApplLayer::handleSelfMsg(msg); } }
4. 清理资源(可选但重要)
在类的析构函数中,确保未处理的消息和定时器被清理,避免内存泄漏:
MyApp::~MyApp() { cancelAndDelete(RstValueEvt); if (pendingBroadcastMsg != nullptr) { delete pendingBroadcastMsg; } }
内容的提问来源于stack exchange,提问作者bettyn
相关产品推荐
相关产品推荐

