Omnet++带时间戳的全序广播ABCAST实现代码调试求助
带时间戳的全序广播(ABCAST)实现问题及优化建议
我正在OMNeT++中尝试实现带时间戳的全序广播(ABCAST):由单个节点向多节点广播消息,接收消息的节点之间也需互相转发该消息。以下是我的.cc文件和NED文件代码,希望有人帮忙指出需要修改或补充的内容,谢谢。
void Res::initialize() { // TODO - Generated method body seq=0; signalID = registerSignal("arrival"); timestamp = 1; if (getIndex() == 0) { //Boot the process scheduling the initial message as a self-message. char msgname[20]; sprintf(msgname, "node-%d", getIndex()); cMessage *msg = new cMessage(msgname); scheduleAt(0.0, msg); } } void Res::handleMessage(cMessage *msg) { if (getIndex() == 3) { // Message arrived. EV << "Message " << msg << " arrived.\n"; delete msg; } else { forwardMessage(msg); } } void Res::forwardMessage(cMessage *msg) { int n = gateSize("out"); int k = intuniform(0, n-1); EV << "Forwarding message " << msg << " on port out [" << k << "]\n"; for (int i = 0; i < n; i++) { cTimestampedValue tmp(timestamp, msg); emit(signalID, &tmp); cMessage *copy = msg->dup(); send(copy, "out", i); } }
simple Broadcast { parameters: @display("i=block/routing"); gates: //inout gate[]; input in[]; // declare in[] and out[] to be vector gates output out[]; } network networ { types: submodules: node[4]: Broadcast ; connections: node[0].out++ --> Channel --> node[1].in++; //node[1].out++ --> Channel --> node[0].in++; node[3].out++ --> Channel --> node[2].in++; node[2].out++ --> Channel --> node[3].in++; node[0].out++ --> Channel --> node[2].in++; node[0].out++ --> Channel --> node[3].in++; } channel Channel extends ned.DelayChannel { delay = 100ms; }
核心问题与修改建议
1. 节点逻辑不符合全序广播要求
- 目前仅节点3处理消息,其他节点直接转发,违背ABCAST“所有节点需接收并处理消息”的核心逻辑。应移除
getIndex() == 3的判断,让所有节点都执行消息处理流程。 - 缺少消息去重机制:当前节点收到消息就转发,会导致无限循环(比如节点1→节点2,节点2又转发回节点1)。需给消息添加唯一标识(发送者ID+序列号),让节点只转发未处理过的消息。
2. 时间戳实现无效
- 固定
timestamp=1无法反映消息时序,应改为使用仿真时间(simTime().dbl())或Lamport逻辑时钟,确保时间戳能区分消息先后。 cTimestampedValue是用于统计信号的工具,不能给消息本身添加时间戳。需自定义消息类(继承cMessage),添加timestamp、senderId、seqNum等成员变量,实现消息时序标识。
3. 网络拓扑不完整
- 当前拓扑中节点1与节点2、节点3之间无连接,无法实现节点间互相转发的要求。应改为全连通拓扑,让每个节点的输出端口连接到其他所有节点的输入端口。
- C类名
Res与NED模块名Broadcast不匹配,需统一两者名称,否则OMNeT无法关联模块与代码。
4. 转发逻辑冗余与错误
forwardMessage中int k = intuniform(0, n-1);是随机单端口转发的冗余代码,后续循环已实现全端口发送,可直接删除。- 初始自消息是普通
cMessage,未携带时间戳和标识,需改为发送自定义消息,初始化必要的时序字段。
示例修改方向
自定义消息类
class ABcastMsg : public cMessage { public: int senderId; int seqNum; double timestamp; ABcastMsg(const char *name) : cMessage(name) {} ABcastMsg(const ABcastMsg& other) : cMessage(other) { senderId = other.senderId; seqNum = other.seqNum; timestamp = other.timestamp; } virtual ABcastMsg *dup() const override { return new ABcastMsg(*this); } };
修改后的initialize方法
void Broadcast::initialize() { seqNum = 0; signalID = registerSignal("arrival"); // 记录已处理的消息,避免重复转发 processedMsgs = new std::unordered_set<std::string>(); if (getIndex() == 0) { ABcastMsg *msg = new ABcastMsg("init-bcast"); msg->senderId = getIndex(); msg->seqNum = seqNum++; msg->timestamp = simTime().dbl(); scheduleAt(0.0, msg); } }
修改后的handleMessage方法
void Broadcast::handleMessage(cMessage *msg) { ABcastMsg *abMsg = check_and_cast<ABcastMsg*>(msg); std::string msgKey = std::to_string(abMsg->senderId) + "-" + std::to_string(abMsg->seqNum); if (processedMsgs->find(msgKey) == processedMsgs->end()) { // 处理消息:可添加全序排序逻辑 EV << "Node " << getIndex() << " received message: " << abMsg->getName() << " | Timestamp: " << abMsg->timestamp << "\n"; processedMsgs->insert(msgKey); // 转发消息到所有其他节点 forwardMessage(abMsg); } else { // 已处理过,直接删除 delete msg; } }
修改后的NED全连通拓扑
simple Broadcast { parameters: @display("i=block/routing"); gates: input in[]; output out[]; } network BroadcastNetwork { types: submodules: node[4]: Broadcast; connections: // 全连通拓扑:每个节点连接到其他所有节点 for i=0..3, for j=0..3 { if i != j { node[i].out++ --> Channel --> node[j].in++; } } } channel Channel extends ned.DelayChannel { delay = 100ms; }
内容的提问来源于stack exchange,提问作者Imane Mezouaghi
相关产品推荐
相关产品推荐

