如何在OMNeT++中创建带三层协议的双节点仿真模型
OMNeT++ 双节点三层协议栈实现指导
1. 项目初始化
- 打开OMNeT++ IDE,创建新的仿真项目,按需选择是否关联INET框架(如果只做简化三层实现可以不关联,完全自定义模块)
- 项目目录下新建3类文件:
.ned(模块定义文件)、.msg(自定义消息结构文件)、.cc(模块逻辑实现文件)
2. NED文件模块定义
首先完成节点和分层结构的声明,示例代码如下:
simple PhysicalLayer { gates: input upperIn; // 接收MAC层下发的消息 output upperOut; // 向MAC层上传收到的消息 input lowerIn; // 接收其他节点物理层发来的信号 output lowerOut; // 向其他节点物理层发送信号 } simple MACLayer { gates: input upperIn; // 接收应用层下发的数据包 output upperOut; // 向应用层上传解封装后的数据包 input lowerIn; // 接收物理层上传的信号 output lowerOut; // 向物理层下发待发送的帧 } simple ApplicationLayer { gates: input lowerIn; // 接收MAC层上传的数据包 output lowerOut; // 向MAC层下发待发送的业务包 } module CustomNode { gates: input wirelessIn; output wirelessOut; submodules: app: ApplicationLayer; mac: MACLayer; phy: PhysicalLayer; connections: app.lowerOut --> mac.upperIn; mac.lowerOut --> phy.upperIn; phy.lowerOut --> wirelessOut; wirelessIn --> phy.lowerIn; phy.upperOut --> mac.lowerIn; mac.upperOut --> app.lowerIn; } network TwoNodeNetwork { submodules: node1: CustomNode; node2: CustomNode; connections: node1.wirelessOut --> node2.wirelessIn; node2.wirelessOut --> node1.wirelessIn; }
注:如果是无线场景,不需要手动连接节点的wireless门,直接使用INET的无线信道模块即可
3. 各层逻辑实现
3.1 Physical层
核心功能:模拟物理层传输特性,包括传输延迟、丢包、信号衰减等
关键实现逻辑示例:
void PhysicalLayer::handleMessage(cMessage *msg) { if (msg->arrivedOn("upperIn")) { // 收到MAC层下发的帧,模拟传输延迟后发送到信道 scheduleAt(simTime() + 0.001, msg); // 1ms传输延迟 } else if (msg->isSelfMessage()) { send(msg, "lowerOut"); } else if (msg->arrivedOn("lowerIn")) { // 收到其他节点的信号,丢包率模拟,比如10%丢包 if (uniform(0,1) < 0.1) { delete msg; return; } send(msg, "upperOut"); } }
3.2 MAC层
核心功能:帧封装/解封装、地址校验、介质访问控制
可以先定义自定义MAC帧结构,创建MacFrame.msg文件:
packet MacFrame { int srcAddr; int dstAddr; int payloadLen; }
OMNeT会自动生成对应的C类,直接调用即可。关键逻辑:
void MACLayer::handleMessage(cMessage *msg) { if (msg->arrivedOn("upperIn")) { // 封装应用层数据包为MAC帧 MacFrame *frame = new MacFrame(); frame->setSrcAddr(getParentModule()->getIndex()); frame->setDstAddr(1 - getParentModule()->getIndex()); // 双节点场景目标地址固定为另一个节点 frame->encapsulate(check_and_cast<cPacket*>(msg)); send(frame, "lowerOut"); } else if (msg->arrivedOn("lowerIn")) { MacFrame *frame = check_and_cast<MacFrame*>(msg); // 地址校验 if (frame->getDstAddr() != getParentModule()->getIndex() && frame->getDstAddr() != 0xFF) { delete frame; return; } // 解封装后上传到应用层 cPacket *payload = frame->decapsulate(); send(payload, "upperOut"); delete frame; } }
3.3 Application层
核心功能:生成业务流量、统计接收数据
关键实现逻辑:
void ApplicationLayer::initialize() { // 节点0主动发数据包 if (getParentModule()->getIndex() == 0) { cMessage *sendEvent = new cMessage("sendEvent"); scheduleAt(simTime() + 1, sendEvent); } } void ApplicationLayer::handleMessage(cMessage *msg) { if (msg->isSelfMessage()) { // 生成业务数据包 cPacket *pkt = new cPacket("AppPacket"); pkt->setByteLength(100); // 100字节 send(pkt, "lowerOut"); // 每隔1s发一个包 scheduleAt(simTime() + 1, msg); } else { // 收到对端发来的数据包,打印日志 EV << "收到数据包,时间:" << simTime() << endl; delete msg; } }
4. 仿真配置
在omnetpp.ini中添加基础配置:
[General] network = TwoNodeNetwork sim-time-limit = 100s **.node*.app.sendInterval = 1s **.node*.phy.packetErrorRate = 0.1
注意事项
- 分层实现时不要跨层直接调用函数,所有交互都通过消息传递实现,保证协议栈的分层独立性
- 复杂消息字段优先通过
.msg文件定义,避免手动写C++类出现序列化错误 - 运行仿真前先检查NED文件中门连接的方向是否正确,避免消息发送报错
内容的提问来源于stack exchange,提问作者Showmik Sadnan
相关产品推荐
相关产品推荐

