Creating an application

23 views
Skip to first unread message

Giuditta Del Sarto

unread,
May 20, 2024, 9:30:59 AMMay 20
to ns-3-users
Good afternoon,

I am developing an ns3 application which desired behavior is the following:
the application should start sending a packet at time m_params.startTime
and should sends every m_params.timeBetweenFrames until m_params.endtime so that it sends a total of totalFrames = (m_params.endTime - m_params.startTime) / m_params.timeBetweenFrames;

However, this application schedule the sending at a certain time x but then it actually sends into the socket at a different time. Moreover, it does all the packets it is supposed to.

Could you help me understanding why?

Thanks in advance

struct FlowParams
{
Time startTime;
Time endTime;
uint32_t bytesPerFrame;
Time timeBetweenFrames;
uint16_t sourcePort;
uint16_t destinationPort;
string protocol;
uint8_t dscp;
};


FlowSender.h:
#include "ns3/core-module.h"
#include "ns3/applications-module.h"
#include "ns3/internet-module.h"
#include "ns3/address.h"
#include "ns3/socket.h"
#include "ns3/tcp-socket-base.h"
#include "ns3/inet-socket-address.h"
#include <utility>
#include "../helper_methods/HelperMethods.h"
#include "FlowParameters.h"

using namespace ns3;
using namespace std;
using namespace helper_methods;

class TcpFlowSender : public Application
{
public:
static TypeId GetTypeId (void);

TcpFlowSender ();

virtual ~TcpFlowSender ();
void Setup (Ptr<Node> node, InetSocketAddress address, const FlowParams& params);
//void Setup (Ptr<Socket> socket, Address address, const FlowParams& params); // Change to take FlowParams as parameter

private:
virtual void StartApplication ();
virtual void StopApplication ();
void SendPacket ();
void ScheduleNextSend();

Ptr<Socket> m_socket;
InetSocketAddress m_peer;
FlowParams m_params; // Store the FlowParams
int m_total = 0;
Time m_lastTime;
};



FlowSender.cc:
#include "Tcp_Application_Sender.h"

NS_LOG_COMPONENT_DEFINE ("TcpFlowSender");
NS_OBJECT_ENSURE_REGISTERED (TcpFlowSender);

TypeId TcpFlowSender::GetTypeId (void)
{
static TypeId tid = TypeId ("TcpFlowSender")
.SetParent<Application> ()
.AddConstructor<TcpFlowSender> ()
;
return tid;
}


TcpFlowSender::TcpFlowSender () : m_peer(InetSocketAddress (Ipv4Address::GetAny()))
{
//m_peer = InetSocketAddress (Ipv4Address::GetAny()); // Initialize m_peer with an empty InetSocketAddress object
m_socket = nullptr;
}

TcpFlowSender::~TcpFlowSender ()
{
m_socket = nullptr;
}

//void TcpFlowSender::Setup (Ptr<Socket> socket, Address address, const FlowParams& params)
void TcpFlowSender::Setup (Ptr<Node> node, InetSocketAddress address, const FlowParams& params)
{
//m_socket = socket;
m_peer = address;
m_params = params; // Store the FlowParams

m_socket = Socket::CreateSocket(node, TcpSocketFactory::GetTypeId());
NS_LOG_INFO("Flow Sender socket created");
// Bind to the specified local port
m_socket->SetSendCallback (MakeNullCallback<void, Ptr<Socket>, uint32_t>());
if(m_socket->Bind(InetSocketAddress(Ipv4Address::GetAny(), m_params.sourcePort)) == -1)
{
NS_FATAL_ERROR("Failed to bind socket!");
}
NS_LOG_INFO("Flow Sender socket bound to local port " << m_params.sourcePort);
}

void TcpFlowSender::StartApplication ()
{
m_peer.SetTos(Dscp2Tos(m_params.dscp));
NS_LOG_INFO ("socket Sender connected, with IpTos: " << unsigned(m_socket->GetIpTos()) << " and DSCP on receiver addr: " << unsigned(m_peer.GetTos()));
if(m_socket->Connect(m_peer) == -1)
{
NS_LOG_INFO("Failed to connect socket!");
}
NS_LOG_INFO("Flow Sender socket connected");
NS_LOG_INFO("Flow Sender starting scheduling packets");

// Send the first packet transmission
m_lastTime = Simulator::Now();
SendPacket();
NS_LOG_INFO("Packet sent to host at time " << Simulator::Now ().GetSeconds () << "s");
}


void TcpFlowSender::StopApplication ()
{
m_socket->Close ();
}

void TcpFlowSender::ScheduleNextSend ()
{
//not used
}

void TcpFlowSender::SendPacket ()
{
// Create packet
Ptr<Packet> packet = Create<Packet> (m_params.bytesPerFrame-54);
// Send packet
m_socket->Send (packet);
NS_LOG_INFO("Packet sent to host at time " << Simulator::Now ().GetSeconds () << "s");
// schedule next send
m_lastTime += m_params.timeBetweenFrames;
if(Simulator::Now() > m_params.endTime)
{
m_socket->Close ();
NS_LOG_INFO("Flow Sender finished sending packets, closing socket. " << endl);
}
else
{
Simulator::Schedule (m_lastTime, &TcpFlowSender::SendPacket, this);
NS_LOG_INFO("Packet scheduled for transmission at time " << m_lastTime.GetSeconds());
}

}

Tommaso Pecorella

unread,
May 20, 2024, 1:23:41 PMMay 20
to ns-3-users
Two small points.

First: you're using TCP, so you're not "sending a packet". TCP will do its own job and will send the bytes (TCP is stream oriented) when it will decide to do so. This can create a non-negligible delay between the Socket Send call and the actual packet(s) sent by the node.

Second: remember that Simulator::Schedule wants a delta time w.r.t. "now". I.e., Simulator::Schedule (Seconds(10), &TcpFlowSender::SendPacket, this); will trigger the function after 10 seconds from "Now". You're using it with an increasing time in the SendPacket function, so you'l have the function called at increasing intervals.
Reply all
Reply to author
Forward
0 new messages