I'm a newbie in OMNeT++ and I want to make a simple broadcast mechanism where starting node sends a msg and it will broadcast it to all nodes connecting in a mesh topology. When msg reaches its destination, the msg will be deleted and does not broadcast further more. Continuously, I'm working on it from 2 days by following it's official documentation. My code is successfully simulated. But it doesn't delete the msg when it reaches to destination. I'm starting with just 25 nodes (computer) in which source node is computer0 and destination node is computer24. Tell me, where I'm wrong. Below is my source code:
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
class computer : public cSimpleModule
{
protected:
virtual void forwardMessage(cMessage *msg);
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(computer);
void computer::initialize()
{
if (getIndex() == 0) {
char msgname[20];
sprintf(msgname, "msg-%d", getIndex());
cMessage *msg = new cMessage(msgname);
scheduleAt(0.0, msg);
}
}
void computer::handleMessage(cMessage *msg)
{
if (getIndex() == 24) {
EV << "Message " << msg << " arrived.\n";
delete msg;
}
else {
forwardMessage(msg);
}
}
void computer::forwardMessage(cMessage *msg)
{
int n = gateSize("gate");
int k = intuniform(0, n-1);
EV << "Forwarding message " << msg << " on gate[" << k << "]\n";
send(msg, "gate$o", k);
}
simulation snap: https://i.stack.imgur.com/a4JRQ.png
You use getIndex() method that return the position of a module in the array of modules. However, the simulation snap shows that you do not use array of modules. Therefore getIndex() returns zero for every module.
The simplest way to correct your model is to check the name of a module instead of its position, for example:
void computer::initialize()
{
// if (getIndex() == 0) {
if (isName("computer0")) {
char msgname[20];
// ...
void computer::handleMessage(cMessage *msg)
{
// if (getIndex() == 24) {
if (isName("computer24")) {
EV << "Message " << msg << " arrived.\n";
// ...
Related
I have written this code that simulates a parking system, however I have a problem when I have to reuse a struct that contains a messageQueue to my carthread. The problem occurs when I try to communicate to the handler for exit with ID_CAR_IND. The struct is send as a message, so I suspect that it gets deleted before arriving, but I can't seem to grasp what is happening, and where it goes wrong. It should be noted that it is a requirement implementation that pthread is used and 3 threads are created.
#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <queue>
#include <time.h>
#include <unistd.h>
#include "Message.h"
#include "MsgQueue.h"
using namespace std;
enum{
ID_START_IND,
ID_ENTRY_REQ,
ID_ENTRY_CFM,
ID_CAR_IND,
ID_STAY_HERE,
ID_EXIT_REQ,
ID_EXIT_OUT,
ID_EXIT_CFM
};
//MESSAGES
struct Car : public Message
{
Car(int carID, MsgQueue* queue) : id(carID), carmq(queue){}
MsgQueue *carmq;
int id;
};
struct OpenReq : public Message
{
MsgQueue *Who_is_asking_;
};
struct CloseReq : public Message
{
MsgQueue *Who_is_asking_exit;
};
struct EntryDoorOpen : public Message{
bool result;
};
MsgQueue entryMq(20);
MsgQueue exitMq(20);
void carHandler(Car* car, unsigned id, Message* msg){
switch(id){
case ID_START_IND:
{
cout << "car " << car->id << " wants to enter" << endl;
OpenReq * req = new OpenReq();
req->Who_is_asking_ = car->carmq;
entryMq.send(ID_ENTRY_REQ, req);
}
break;
case ID_ENTRY_CFM:
{
cout << "car " << car->id << " entered parking" << endl;
entryMq.send(ID_CAR_IND);
}
break;
case ID_STAY_HERE:
{
}
break;
case ID_EXIT_CFM:
{
cout << "car " << car->id << "Left parking" << endl;
exitMq.send(ID_EXIT_OUT);
}
break;
default:
break;
}
}
void entryHandler(unsigned id, Message* msg){
OpenReq* req=static_cast<OpenReq*>(msg);
switch(id){
case ID_ENTRY_REQ:
{
cout << "Access granted. Opening entry door " << endl;
req->Who_is_asking_->send(ID_ENTRY_CFM);
}
break;
case ID_CAR_IND:
{
cout << "Closing entry door " << endl;
sleep(2);
req->Who_is_asking_->send(ID_EXIT_REQ);
}
break;
default:
break;
}
}
void exitHandler(unsigned id, Message * msg)
{
OpenReq* req = static_cast<OpenReq*>(msg);
switch(id)
{
case ID_EXIT_REQ:
{
cout << "Leaving is Granted. Opening exit door" << endl;
req->Who_is_asking_->send(ID_EXIT_CFM);
}
break;
case ID_EXIT_OUT:
{
cout << "Car has left the parkinglot" << endl;
}
break;
default:
break;
}
}
void *car(void* data){
Car *car = static_cast<Car*>(data);
car->carmq->send(ID_START_IND);
for(;;){
unsigned long id;
Message *msg = car->carmq->receive(id);
carHandler(car,id,msg);
delete(msg);
}
}
void *entry(void* data){
for(;;){
unsigned long id;
Message *msg = entryMq.receive(id);
entryHandler(id,msg);
delete(msg);
}
}
void *exit(void * data){
for(;;){
unsigned long id;
Message *msg = exitMq.receive(id);
exitHandler(id,msg);
delete(msg);
}
}
int main()
{
MsgQueue q(10);
Car carObj(1, &q);
pthread_t carThread, entryThread;
pthread_create(&carThread,nullptr,car, &carObj);
pthread_create(&entryThread,nullptr,entry, nullptr);
pthread_join(carThread,nullptr);
return 0;
}
//
// Created by stud on 11/3/19.
//
#include "MsgQueue.h"
#include "Message.h"
#include <iostream>
MsgQueue::MsgQueue(unsigned long maxSize) : maxSize_(maxSize)
{
//Init pthread funktionerne.
pthread_mutex_init(&msgmutex, NULL);
pthread_cond_init(&msgcond,NULL);
};
void MsgQueue::send(unsigned long id, Message* msg)
{
pthread_mutex_lock(&msgmutex);
while(msgqueue_.size() == maxSize_)
{
pthread_cond_wait(&msgcond, &msgmutex);
}
info besked;
besked.id = id;
besked.msg = msg;
msgqueue_.push(besked);
pthread_cond_broadcast(&msgcond);
pthread_mutex_unlock(&msgmutex);
//std::cout << "sending from id #" << id << std::endl;
};
Message* MsgQueue::receive(unsigned long&id)
{
pthread_mutex_lock(&msgmutex);
while(msgqueue_.empty())
{
pthread_cond_wait(&msgcond,&msgmutex);
}
info besked;
besked = msgqueue_.front();
id = besked.id;
msgqueue_.pop();
pthread_cond_broadcast(&msgcond);
pthread_mutex_unlock(&msgmutex);
return besked.msg;
};
MsgQueue::~MsgQueue()
{
pthread_mutex_destroy(&msgmutex);
pthread_cond_destroy(&msgcond);
};
//
// Created by stud on 11/3/19.
//
#pragma once
#include <iostream>
#include <pthread.h>
#include "Message.h"
#include <queue>
struct info : public Message
{
unsigned long id;
Message* msg;
};
class MsgQueue
{
public:
MsgQueue(unsigned long maxSize);
void send(unsigned long id, Message* msg = NULL);
Message* receive(unsigned long&id);
~MsgQueue();
private:
unsigned long maxSize_;
std::queue <info> msgqueue_;
pthread_cond_t msgcond;
pthread_mutex_t msgmutex;
};
//
//
//
#pragma once
class Message
{
public:
virtual ~Message(){};
};
The question currently lacks a few details (like details about what exactly your problem is, including any error message you get), but we can speculate some on what the problem is. Since the problem is with ID_CAR_IND, lets start by examining the handler for that message. It prints a message, then dereferences a pointer that is a property of the message. Nothing obviously wrong there.
So let's check where we create that message. It sends just the message ID. Furthere investigation shows that send takes an optional second parameter. Since it is not provided, this will be a nullptr in the message that is sent.
Since this extra message data is needed by the message handler, and not provided, this results in dereferencing a null pointer in the handler, resulting in Undefined Behavior and (typically) a crash of the program with something like an access violation error.
The solution is to pass an OpenReq object to send (like you are for the ID_START_IND message).
Consider revising the code to check or remove consecutive uses of the -> operator. There is some way in which the code cannot catch the null value.
Why don't you use OS API instead of implementing your own MsgQueue?
I know, this may be a lot to ask, but can anyone help me debug this code:
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
class Node : public cSimpleModule
{
private:
cMessage *out_msg;
long no_sent = 0;
long no_rcvd = 0;
cOutVector rcvdRecord;
cLongHistogram Statistics;
public:
Node();
virtual ~Node();
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
virtual void finish() override;
};
Define_Module(Node);
Node::Node()
{
out_msg = nullptr;
}
Node::~Node()
{
delete out_msg;
}
void Node::initialize()
{
out_msg = nullptr;
if (strcmp("sender", getName()) == 0) {
EV << "Scheduling first send to t=5.0s\n";
scheduleAt(5.0, out_msg);
out_msg = new cMessage("Sending Message");
}
}
void Node::handleMessage(cMessage *msg)
{
if (msg == out_msg) {
EV << "Sending message to receiver\n";
send(out_msg, "out");
out_msg = nullptr;
no_sent++;
simtime_t delay = par("delayTime");
scheduleAt(simTime() + delay, out_msg);
}
else {
out_msg = msg;
no_rcvd++;
rcvdRecord.record(out_msg);
Statistics.collect(out_msg); //what's going on here ?
}
}
void Node::finish()
{
EV << "Sent: " << no_sent << endl;
EV << "Received: " << no_rcvd << endl;
EV << "Messages sent, mean: " << Statistics.getMean() << endl;
EV << "Messages sent, standard deviation: " << Statistics.getStddev() << endl;
EV << "Messages sent, variance: " << Statistics.getVariance() << endl;
recordScalar("#sent", no_sent);
recordScalar("#received", no_rcvd);
Statistics.recordAs("Message Statistics");
}
I get the following error message:
Exercise2.cc:66:38: error: no matching function for call to
'omnetpp::cOutVector::record(omnetpp::cMessage*&)'
Exercise2.cc:67:39: error: no matching function for call to
'omnetpp::cLongHistogram::collect(omnetpp::cMessage*&)'
So I really don't know what this is supposed to tell me. Aren't these built-in functions, part of the cOutVector or cLongHistogram classes respectively?
Aren't these built-in functions, part of the cOutVector or
cLongHistogram classes respectively?
They aren't. Well, cOutVector does have a member function named record, it just can't take a cMessage * as an argument, so that specific function overload you wanted to use doesn't exist. Same with cLongHistogram and collect.
Just take a look at the documentation:
A cOutVector object can write doubles to the output vector file ...
And, by the way, what exactly do you expect to see as a "histogram of messages"? :D This comic comes to my mind...
To record the messages (not into a cOutVector), you can enable event logging. The resulting file can be visualized in the Sequence Chart tool of the IDE, see: https://docs.omnetpp.org/tutorials/tictoc/part2/#25-visualizing-on-a-sequence-chart
I've started learning POCO C++ library and I'm stuck while trying to run 2 servers in the same application (so that they can use some common runtime variables). These are 2 different servers, one of them is TCP TimeServer and the other one is simple UDP EchoServer. The code:
#include "Poco/Net/TCPServer.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Net/TCPServerParams.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Timestamp.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Exception.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>
using Poco::Net::ServerSocket;
using Poco::Net::StreamSocket;
using Poco::Net::TCPServerConnection;
using Poco::Net::TCPServerConnectionFactory;
using Poco::Net::TCPServer;
using Poco::Timestamp;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
class TimeServerConnection : public TCPServerConnection
{
public:
TimeServerConnection(const StreamSocket& s, const std::string& format) :
TCPServerConnection(s),
_format(format)
{
}
void run()
{
Application& app = Application::instance();
bool isOpen = true;
Poco::Timespan timeOut(10, 0);
unsigned char incommingBuffer[1000];
app.logger().information("SYSLOG from " + this->socket().peerAddress().toString());
while (isOpen) {
if (socket().poll(timeOut, Poco::Net::Socket::SELECT_READ) == false) {
std::cout << "TIMEOUT!" << std::endl << std::flush;
} else {
int nBytes = -1;
try {
nBytes = socket().receiveBytes(incommingBuffer, sizeof(incommingBuffer));
std::cout << incommingBuffer << std::endl;
} catch (Poco::Exception& exc) {
std::cerr << "Network error: " << exc.displayText() << std::endl;
isOpen = false;
}
if (nBytes == 0) {
std::cout << "Client closes connection!" << std::endl << std::flush;
isOpen = false;
} else {
std::cout << "Receiving nBytes: " << nBytes << std::endl << std::flush;
}
}
}
try
{
Timestamp now;
std::string dt(DateTimeFormatter::format(now, _format));
dt.append("\r\n");
socket().sendBytes(dt.data(), (int)dt.length());
}
catch (Poco::Exception& exc)
{ app.logger().log(exc); }
}
private:
std::string _format;
};
class TimeServerConnectionFactory : public TCPServerConnectionFactory
{
public:
TimeServerConnectionFactory(const std::string& format) :
_format(format)
{
}
TCPServerConnection* createConnection(const StreamSocket& socket)
{ return new TimeServerConnection(socket, _format); }
private:
std::string _format;
};
class UDPServer : public Poco::Util::ServerApplication
{
public:
UDPServer(){}
~UDPServer(){}
protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void uninitialize() { ServerApplication::uninitialize(); }
int main(const std::vector<std::string>& args)
{
unsigned short port = (unsigned short)config().getInt("udpport", 9002);
std::cout << "[UDP] Using port " << port << std::endl;
std::string format(config().getString("TimeServer.format", DateTimeFormat::ISO8601_FORMAT));
Poco::Net::SocketAddress socketaddress(Poco::Net::IPAddress(), 9001);
Poco::Net::DatagramSocket datagramsocket(socketaddress);
char buffer[1024]; // 1K byte
while (1) {
Poco::Net::SocketAddress sender;
int n = datagramsocket.receiveFrom(buffer, sizeof(buffer) - 1, sender);
buffer[n] = '\0';
std::cout << sender.toString() << ":" << buffer << std::endl;
}
return 0;
}
};
class TimeServer : public Poco::Util::ServerApplication
{
public:
TimeServer() : _helpRequested(false)
{
}
~TimeServer()
{
}
protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void uninitialize()
{
ServerApplication::uninitialize();
}
void defineOptions(OptionSet& options)
{
ServerApplication::defineOptions(options);
options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false));
}
void handleOption(const std::string& name, const std::string& value)
{
ServerApplication::handleOption(name, value);
if (name == "help")
_helpRequested = true;
}
void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A server application that serves the current date and time.");
helpFormatter.format(std::cout);
}
int main(const std::vector<std::string>& args)
{
if (_helpRequested)
{
displayHelp();
}
else
{
unsigned short port = (unsigned short)config().getInt("tcpport", 9911);
std::cout << "Using port " << port << std::endl;
std::string format(config().getString("TimeServer.format", DateTimeFormat::ISO8601_FORMAT));
ServerSocket svs(port);
TCPServer srv(new TimeServerConnectionFactory(format), svs);
srv.start();
std::cout << "Server started!\n";
waitForTerminationRequest();
srv.stop();
std::cout << "Server stopped!\n";
}
return Application::EXIT_OK;
}
private:
bool _helpRequested;
};
int main(int argc, char** argv)
{
TimeServer app;
UDPServer app2;
app.run(argc, argv);
app2.run(argc, argv);
}
In the end of code I have int main() method where I'm trying to run 2 servers. However I get assertion violation here. There is a similar question on StackOverflow, however boost is used there while I'm using plain C++, so that solution is not relevant to me.
How can I run simultaneously these 2 servers?
ServerApplication was not designed for multiple instances. What you should do is run one ServerApplication and launch TCPServer and UDPServer in that application.
Actually if you want to made like this (as you question), seperated both
tcp (a) class and
udp (b) class.
Call both in other class (c) and
define which one
(c) -> (a)
(c) -> (b)
u need to call first and when. So u need make condition and decision.
Note: give them space time before run to made poco breath. 😂
I have below code of Mosquitto that subscribe to the particular topic in c++.
main.cpp
/*
* main.cpp
*
* Created on: Jul 28, 2016
* Author: nilav
*/
#include <iostream>
#include "myMosq.h"
#include <string.h>
#include <unistd.h>
using namespace std;
int main() {
myMosq *mosq;
mosq = new myMosq("unique","topic", "localhost",1883);
int res;
while(1) {
char tstr[500] ;
// cin.getline(tstr,sizeof(tstr));
sleep(2);
// mosq->send_message(tstr);
mosq->receive_message(tstr);
res = mosq->loop(); // Keep MQTT connection
if (res)
mosq->reconnect();
}
}
myMosq.h
/*
* myMosq.h
*
* Created on: Jul 28, 2016
* Author: nilav
*/
#ifndef MYMOSQ_H_
#define MYMOSQ_H_
#include <mosquittopp.h>
#include <mosquitto.h>
class myMosq : public mosqpp::mosquittopp
{
private:
const char * host;
const char * id;
const char * topic;
int port;
int keepalive;
void on_connect(int rc);
void on_disconnect(int rc);
void on_subscribe(int mid, int qos_count, const int *granted_qos);
public:
myMosq(const char *id, const char * _topic, const char *host, int port);
~myMosq();
bool send_message(const char * _message);
bool receive_message(const char * _message);
};
#endif
myMosq.cpp
#include <cstdio>
#include <cstring>
#include <iostream>
#include "myMosq.h"
#include <mosquittopp.h>
using namespace std;
myMosq::myMosq(const char * _id,const char * _topic, const char * _host, int _port) : mosquittopp(_id)
{
mosqpp::lib_init(); // Mandatory initialization for mosquitto library
this->keepalive = 60; // Basic configuration setup for myMosq class
this->id = _id;
this->port = _port;
this->host = _host;
this->topic = _topic;
connect_async(host, // non blocking connection to broker request
port,
keepalive);
loop_start(); // Start thread managing connection / publish / subscribe
};
myMosq::~myMosq() {
loop_stop(); // Kill the thread
mosqpp::lib_cleanup(); // Mosquitto library cleanup
}
//bool myMosq::send_message(const char * _message)
// {
// int ret = publish(NULL,this->topic,strlen(_message),_message,1,false);
// cout << ret;
// return ( ret == MOSQ_ERR_SUCCESS );
// }
bool myMosq::receive_message(const char * message)
{
int set = subscribe(NULL, this->topic,2);
return set;
}
void myMosq::on_disconnect(int rc) {
std::cout << ">> myMosq - disconnection(" << rc << ")" << std::endl;
}
void myMosq::on_connect(int rc)
{
if ( rc == 0 ) {
std::cout << ">> myMosq - connected with server" << std::endl;
} else {
std::cout << ">> myMosq - Impossible to connect with server(" << rc << ")" << std::endl;
}
}
void myMosq::on_subscribe(int mid, int qos_count, const int *granted_qos)
{
std::cout << ">> subscription succeeded (" << mid << ") " << std::endl;
printf("Subscription succeeded.\n");
}
Now when I issue following command from terminal of ubuntu
mosquitto_pub -h localhost -t "topic" -m "Hello MQTT"
nothing is displayed in the program output. But I want a code that display the particular message produced in particular topic when subscribed.
Any help will be appreciated.
There is an error in the way you set up the bool myMosq::receive_message(const char * message) function. As far as MQTT works, you initially subscribe once to a topic and then use the provided loop function of the mosquittopp wrapper to check for changed data on the corresponding topics. Now you only have to specify, what should happen on the void on_message(const struct mosquitto_message* message) callback and grab and format the message object according to the used data type.
For example, to grab some kind of char-related data my overload implementation looks like this:
void MQTTSubscriber::on_message(const mosquitto_message* message)
{
cout << "Subscriber " << id << " received message of topic: " << message->topic << " Data: " << reinterpret_cast<char*>(message->payload) << "\n";
}
The connect_async() does all the work for establishing and keeping your broker connection and the loop_start() function handles the thread-separate callback functions.
Best regards,
Richard
I try to write a little client-server program. A client should detect all servers running in the same LAN. I tried to implement a UDP-Broadcast with qt but my read function returns -1 all the time. If I call the dataAvailable()-function on the socket, it says that 4 bytes are available to read, but for some reason it fails to read them.
For now I'm trying to receive the broadcast on the same machine and in the same program
Here's my main:
#include <iostream>
#include <QString>
#include <QThread>
#include "../include/network.h"
using namespace std;
using namespace network;
int main () {
Network *n = new Network ();
n->broadcast("test");
if (n->dataAvailable()) {
cout << "Data available: ";
cout << n->getData().toStdString() << std::endl;
} else {
cout << "No data" << endl;
}
delete n;
}
and my Network-class:
#ifndef NETWORK
#define NETWORK
#include <QObject>
#include <QUdpSocket>
#include <iostream>
namespace network {
class Network : public QObject {
Q_OBJECT
public:
const static int BROADCAST_PORT = 52433;
explicit Network(QObject *parent = 0) {
socket = new QUdpSocket ();
socket->bind (QHostAddress::Any, BROADCAST_PORT);
}
~Network () {
delete socket;
}
bool dataAvailable () {
return socket->hasPendingDatagrams();
}
QString getData () {
if (!dataAvailable()) {
return "";
}
char *data = 0;
std::cout << socket->pendingDatagramSize() << std::endl;
std::cout << QString("recv: %1")
.arg(socket->readDatagram(data,
socket->pendingDatagramSize())).toStdString();
return QString(data);
}
void broadcast(QString data) {
QUdpSocket *broadcast = new QUdpSocket ();
broadcast->connectToHost(QHostAddress::Broadcast, BROADCAST_PORT);
std::cout << broadcast->write(data.toStdString().c_str())
<< std::endl << std::endl;
delete broadcast;
}
private:
QUdpSocket *socket;
};
}
#endif // NETWORK
the Output is the following:
4
Data available: 4
recv -1
Which means
4 Bytes are sent from the broadcast
the socket detects that 4 bytes are available
the attempt to read the 4 bytes fails
the QString returned by getData() is empty
Unfortunately I could not find any possibility to get more information on the error
You definitely need to allocate memory for reading datagram. Now you try to write it to null pointer.
// char *data = 0;
std::cout << socket->pendingDatagramSize() << std::endl;
QVector<char> buffer(socket->pendingDatagramSize()); // create buffer
std::cout << QString("recv: %1")
.arg(socket->readDatagram(buffer.data(),
socket->pendingDatagramSize())).toStdString();