Code
Code
ini:
[General]
network = GoBackN
[Config GoBackN]
description = "Simulation of Go-Back-N ARQ protocol"
**.sender.dataRate = 0.5s # 每 0.5 秒发送一个数据包
**.sender.timeout = 2s # 超时时间为 2 秒
**.sender.windowSize = 8
**.receiver.windowSize = 8
**.receiver.N = 3 # 每接收 3 个数据包发送一个 ACK
**.receiver.packetLossRate = 0.1 # 数据包丢失率为 10%
GoBackN.ned
network GoBackN
{
submodules:
sender: Sender {
parameters:
@display("p=113,212");
}
receiver: Receiver {
parameters:
@display("p=300,100");
}
connections:
sender.out --> { @display("m=s"); } --> receiver.in;
receiver.out --> { @display("m=s"); } --> sender.in;
}
simple Sender
{
parameters:
int windowSize; // 窗口大小参数
double dataRate @unit(s) = default(1s);
double timeout @unit(s) = default(1s);
gates:
input in;
output out;
}
simple Receiver
{
parameters:
int windowSize = default(5); // 窗口大小参数
int N = default(2); // 接收阈值参数
double packetLossRate = default(0.1); // 包丢失率参数
gates:
input in;
output out;
}
Sender.cc
#include <omnetpp.h>
#include <vector>
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
void sendDataPacket();
void handleAckPacket(cMessage *msg);
void handleTimeout();
void queryReceiverWindowSize();
void handleQueryReply(cMessage *msg);
};
Define_Module(Sender);
void Sender::initialize() {
sequenceNumberLimit = 256; // 8-bit sequence number limit
windowSize = 0; // Initial window size, will be set after query
dataRate = par("dataRate");
timeout = par("timeout");
nextSequenceNumber = 0;
base = 0;
timeoutEvent = new cMessage("timeoutEvent");
sendNextPacketEvent = new cMessage("sendNextPacket");
void Sender::queryReceiverWindowSize() {
cMessage *query = new cMessage("query_request");
send(query, "out");
}
void Sender::sendDataPacket() {
if ((nextSequenceNumber + sequenceNumberLimit - base) %
sequenceNumberLimit < windowSize) {
cMessage *dataPacket = new cMessage("dataPacket");
dataPacket->setKind(nextSequenceNumber);
window.push_back(dataPacket);
send(dataPacket->dup(), "out");
EV << "Sending packet with sequence number " <<
nextSequenceNumber << " to TOC.\n";
nextSequenceNumber = (nextSequenceNumber + 1) %
sequenceNumberLimit;
cancelEvent(sendNextPacketEvent);
scheduleAt(simTime() + dataRate, sendNextPacketEvent);
cancelEvent(timeoutEvent);
EV << "Received ACK for sequence number " << ackNum << ".
Timer cancelled.\n";
if (base != nextSequenceNumber) {
scheduleAt(simTime() + timeout, timeoutEvent);
}
void Sender::handleTimeout() {
EV << "Timeout occurred, resending packets.\n";
for (int i = base; i != nextSequenceNumber; i = (i + 1) %
sequenceNumberLimit) {
send(window[i]->dup(), "out");
}
scheduleAt(simTime() + timeout, timeoutEvent);
}
Receiver.cc:
#include <omnetpp.h>
#include <queue>
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
void sendAckPacket(int seqNum);
void handleDataPacket(cMessage *msg);
bool isPacketLost();
void handleQueryRequest(cMessage *msg);
};
Define_Module(Receiver);
void Receiver::initialize() {
sequenceNumberLimit = 256; // 8-bit sequence number limit
windowSize = par("windowSize");
N = par("N");
packetLossRate = par("packetLossRate");
expectedSequenceNumber = 0;
receivedCount = 0;
}
if (seqNum == expectedSequenceNumber) {
EV << "Received expected packet: " << seqNum << "\n";
expectedSequenceNumber = (expectedSequenceNumber + 1) %
sequenceNumberLimit;
receivedCount++;
if (receivedCount >= N) {
EV << "Sending ACK for sequence number " << seqNum << "\
n";
sendAckPacket(seqNum);
receivedCount = 0;
}
} else {
EV << "Received out-of-order packet: " << seqNum << "\n";
sendAckPacket((expectedSequenceNumber +
sequenceNumberLimit - 1) % sequenceNumberLimit); // Send NAK
}
buffer.push(msg);
}
bool Receiver::isPacketLost() {
return uniform(0, 1) < packetLossRate;
}