0% found this document useful (0 votes)
5 views7 pages

Code

The document outlines the configuration and implementation of a Go-Back-N ARQ protocol simulation, detailing the sender and receiver modules with their parameters and behaviors. It includes specifications for data rates, timeout settings, window sizes, and packet loss rates. The code snippets illustrate the logic for sending and receiving packets, handling acknowledgments, and managing timeouts in the simulation environment.

Uploaded by

mlin41088
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views7 pages

Code

The document outlines the configuration and implementation of a Go-Back-N ARQ protocol simulation, detailing the sender and receiver modules with their parameters and behaviors. It includes specifications for data rates, timeout settings, window sizes, and packet loss rates. The code snippets illustrate the logic for sending and receiving packets, handling acknowledgments, and managing timeouts in the simulation environment.

Uploaded by

mlin41088
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

GoBackN.

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>

using namespace omnetpp;

class Sender : public cSimpleModule {


private:
int windowSize;
double dataRate;
double timeout;
int nextSequenceNumber;
int base;
cMessage *timeoutEvent;
cMessage *sendNextPacketEvent;
std::vector<cMessage*> window;
int sequenceNumberLimit;

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");

// Query receiver window size


queryReceiverWindowSize();
}

void Sender::handleMessage(cMessage *msg) {


if (msg == timeoutEvent) {
handleTimeout();
} else if (msg == sendNextPacketEvent) {
sendDataPacket();
} else if (strcmp(msg->getName(), "query_reply") == 0) {
handleQueryReply(msg);
} else {
handleAckPacket(msg);
}
}

void Sender::queryReceiverWindowSize() {
cMessage *query = new cMessage("query_request");
send(query, "out");
}

void Sender::handleQueryReply(cMessage *msg) {


windowSize = msg->par("windowSize");
sendDataPacket();
delete msg;
}

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);

if (base == (nextSequenceNumber + sequenceNumberLimit - 1)


% sequenceNumberLimit) {
scheduleAt(simTime() + timeout, timeoutEvent);
}
}
}

void Sender::handleAckPacket(cMessage *msg) {


int ackNum = msg->par("ackNum");
if ((ackNum + sequenceNumberLimit - base) %
sequenceNumberLimit < windowSize) {
base = (ackNum + 1) % sequenceNumberLimit;

cancelEvent(timeoutEvent);
EV << "Received ACK for sequence number " << ackNum << ".
Timer cancelled.\n";

if (base != nextSequenceNumber) {
scheduleAt(simTime() + timeout, timeoutEvent);
}

if ((nextSequenceNumber + sequenceNumberLimit - base) %


sequenceNumberLimit < windowSize) {
sendDataPacket();
}
}
delete msg;
}

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>

using namespace omnetpp;

class Receiver : public cSimpleModule {


private:
int windowSize;
int N;
double packetLossRate;
int expectedSequenceNumber;
int receivedCount;
std::queue<cMessage*> buffer;
int sequenceNumberLimit;

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;
}

void Receiver::handleMessage(cMessage *msg) {


if (strcmp(msg->getName(), "query_request") == 0) {
handleQueryRequest(msg);
} else {
handleDataPacket(msg);
}
}

void Receiver::handleQueryRequest(cMessage *msg) {


cMessage *reply = new cMessage("query_reply");
reply->addPar("windowSize") = windowSize;
send(reply, "out");
delete msg;
}

void Receiver::sendAckPacket(int seqNum) {


cMessage *ackPacket = new cMessage("ack");
ackPacket->addPar("ackNum") = seqNum;
send(ackPacket, "out");
}

void Receiver::handleDataPacket(cMessage *msg) {


int seqNum = msg->getKind();
if (isPacketLost()) {
EV << "Packet loss: " << seqNum << "\n";
delete msg;
return;
}

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;
}

You might also like