Qt UDP read error - c++

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

Related

Unable to receive UDP message packets through receiveFrom API of Poco Library. It doesnt return from the receiveFrom API

Able to send UDP message to a particular IP port using Poco Lib socket communication, But unable to receive the UDP message as it is getting stuck at receiveFrom API of DatagramSocket as in below code.
I am sending message every second and also have to receive acknowledgement every second, for that i have timer , Client and Server Threads running parallelly. The problem here is I am unable to receive the UDP packets which are being captured on wireshark. It is getting stuck at receiveFrom.
Please find below Client Server and main files.
` Server.hpp
#pragma once
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/MulticastSocket.h"
#include "Poco/RunnableAdapter.h"
#include "Poco/Thread.h"
#include <cstring>
#include <iostream>
using namespace std;
using namespace Poco;
using namespace Poco::Net;
struct Server
{
int bufferSize;
SocketAddress sockets;
static bool debugModeEnabled;
Server() :
bufferSize(1024) { //sockets = SocketAddress(10000);
}
Server(const UInt16& port, const int& bufferSize)
{
sockets = SocketAddress(port);
this->bufferSize = bufferSize;
}
void receiveMessages()
{
char buffer[bufferSize];
try
{
Poco::Net::DatagramSocket datagram(sockets);//(socket);
datagram.bind(sockets);
cout << "Server started socket" << endl;
while (!datagram.available())
{
SocketAddress sender;
cout << "Server started socket 2" << endl;
int size = datagram.receiveFrom(buffer, bufferSize, sender);
//int size = datagram.receiveBytes(buffer, bufferSize);
cout << "received bytes size" << size << endl;
buffer[size] = '\0';
//std::string str(buffer);
//cout << (debugModeEnabled ? (sender.toString() + ": ") : "- ") << buffer << endl;
cout << "received: " << size << buffer << endl;
//cout << buffer << "Server adasdasd" << endl;
if (string(buffer) == "\\end")
{
//cerr << "\nUser: " << sender.toString() << " ended connection" << endl;
datagram.close(); // Closes the server
}
}
}
catch (const Poco::Exception& exc)
{
std::cerr << exc.displayText() << std::endl;
}
}
};
bool Server::debugModeEnabled = false;
`
`Client.hpp
#pragma once
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/RunnableAdapter.h"
#include "Poco/Thread.h"
#include <iostream>
#include <string>
using namespace std;
using namespace Poco;
using namespace Poco::Net;
struct Client
{
SocketAddress socket;
string str;
// By default the client connects to itself
Client() { socket = SocketAddress("127.0.0.1", 10000); }
Client(const Poco::Net::IPAddress& IP, const UInt16& port, const string& val) :
str(val)
{
socket = SocketAddress(IP, port);
}
void sendMessages()
{
DatagramSocket datagram;
datagram.connect(socket);
string message = str;
//cout << "sending: " << hex << hexify(message) << endl;
unsigned int bytes_sent = 0;
while (!datagram.available())
{
//getline(cin, message);
//bytes_sent = datagram.sendBytes(message.data(), static_cast<int>(message.size()));
bytes_sent = datagram.sendTo(message.data(), static_cast<int>(message.size()),socket);
cout << "number of bytes sent: " << std::dec << bytes_sent << endl;
if (bytes_sent >= message.size())
{
datagram.close();
}
}
}
string IP() { return socket.host().toString(); }
UInt16 port() { return socket.port(); }
static void sendMessage(const Poco::Net::IPAddress& IP, const UInt16& port, const string& message)
{
SocketAddress socket(IP, port);
DatagramSocket datagram;
datagram.connect(socket);
datagram.sendBytes(message.data(), int(message.size()));
}
};
`
` main.cpp
int bufferSize = 1024;
int exit_status = 0;
Client client(IP, ciPort, str);
Server server(mdilPort, bufferSize);
RunnableAdapter<Client> clientRunnable(client, &Client::sendMessages);
RunnableAdapter<Server> serverRunnable(server, &Server::receiveMessages);
Thread clientThread, serverThread;
// Client::sendMessage(IP, ciPort, "hello!!");
try
{
Timer t = Timer();
t.setInterval([&]() {
cout << "client Tick" << endl;
// pApp->SendIndications();
clientThread.start(clientRunnable);
clientThread.join();
},
1000);
t.setInterval([&]() {
cout<< "server Tick" << endl;
serverThread.start(serverRunnable);
serverThread.join();
},
1000);
t.setTimeout([&]() {
std::cout << "Hey.. After 30s. But I will stop the timer!" << std::endl;
t.stop();
exit(exit_status);
},
30000);
std::cout << "I am Timer" << std::endl;
while (true); // Keep main thread active
}
catch (...)
{
std::cout << "catched exception" << std::endl;
//return -1;
}
`
I tried the conventional Socket Programming API's to receive the UDP packets but there also it is getting stuck at receiveFrom API. also tried running both client and server on different process to make sure there is no issue with the multi threading synchronization, but both the approach didnt help. I am able to capture the response at Wireshark but unable to receive on the application side using Poco Lib socket API's. Also allowed visual studio code through firewall as well

Why Qt serial read data never arrives? (Qt 5.15.2, C++, Win64, MSVC2019_64)

To develop my program first without connecting two physical machines on serial port, I downloaded and used this program to simulate COM ports:
https://sourceforge.net/projects/com0com/
I connected virtual COM4 to virtual COM5. It works fine.
Using Br#y's Terminal program, I tested if I connect to COM4 in one Terminal instance, and to COM5 in another instance on the same computer, the data that I send on one terminal arrives in the other terminal, and vice versa.
Terminal program: https://sites.google.com/site/terminalbpp/
Now let's see the problem:
I used SerialPortReader class from this official Qt sample code for async serial read: https://code.qt.io/cgit/qt/qtserialport.git/tree/examples/serialport/creaderasync
It connects to COM5 and sets baud rate to 9600 successfully, but no data arrives if I send something via Terminal to COM4, so: SerialPortReader runs through with no error, but after then, no matter what message I send on my Terminal instance, handleReadyRead, handleError, and handleTimeout never get called.
(If I have already a terminal emulator connected to the virtual COM5 port, then connection in my C++ program fails, so indeed the open() check works fine.
Also, if I try to send more than one messages to my program via the virtual COM4 port, Terminal freezes, which is a clear sign of that the previous message has not yet been read on the other side(COM5).)
I have googled a lot, but have not yet found any solutions. Someone here said that it is/was a bug Qt Serial Port Errors - Data not getting read and that the problem is in qserialport_win.cpp, but even if I change that and compile my program again, nothing happens.
I use the following code to create the class, but the class' content is unchanged, I use it as I found in the sample program:
// Serial comm init
QSerialPort serialPort;
QString serialPortName = "COM5";
serialPort.setPortName(serialPortName);
int serialPortBaudRate = 9600;
if (serialPort.open(QIODevice::ReadOnly)) {
if(serialPort.setBaudRate(serialPortBaudRate) &&
serialPort.setDataBits(QSerialPort::Data8) &&
serialPort.setParity(QSerialPort::NoParity) &&
serialPort.setStopBits(QSerialPort::OneStop) &&
serialPort.setFlowControl(QSerialPort::NoFlowControl)) {
//SerialPortReader serialPortReader(&serialPort);
SerialPortReader serialPortReader(&serialPort, this);
} else {
std::cout << "Failed to set COM connection properties " << serialPortName.toStdString() << serialPort.errorString().toStdString() << std::endl;
}
} else {
std::cout << "Failed to open port " << serialPortName.toStdString() << serialPort.errorString().toStdString() << std::endl;
}
I would appreciate any help. Thanks!
Today I figured out a sketchy but working version:
SerialPortReader.h
#pragma once
#include <QtCore/QObject>
#include <QByteArray>
#include <QSerialPort>
#include <QTextStream>
#include <QTimer>
class SerialPortReader : public QObject {
Q_OBJECT
public:
explicit SerialPortReader(QObject *parent = 0);
~SerialPortReader() override;
void close();
private:
QSerialPort *serialPort = nullptr;
QByteArray m_readData;
QTimer m_timer;
public slots:
void handleReadyRead();
//void handleTimeout();
//void handleError(QSerialPort::SerialPortError error);
};
SerialPortReader.cpp
#include <iostream>
#include "SerialPortReader.h"
SerialPortReader::SerialPortReader(QObject *parent) : QObject(parent)
{
serialPort = new QSerialPort(this);
const QString serialPortName = "COM4"; //argumentList.at(1);
serialPort->setPortName(serialPortName);
const int serialPortBaudRate = QSerialPort::Baud9600;
serialPort->setBaudRate(serialPortBaudRate);
if (!serialPort->open(QIODevice::ReadOnly)) {
std::cout << "Failed to open port" << std::endl;
//return 1;
}
std::cout << "SerialPortReader(QSerialPort *serialPort, QObject *parent)" << std::endl;
connect(serialPort, SIGNAL(readyRead()), this, SLOT(handleReadyRead()), Qt::QueuedConnection);
// connect(serialPort, &QSerialPort::readyRead, this, &SerialPortReader::handleReadyRead);
//connect(serialPort, &QSerialPort::errorOccurred, this, &SerialPortReader::handleError);
//connect(&m_timer, &QTimer::timeout, this, &SerialPortReader::handleTimeout);
//m_timer.start(5000);
}
void SerialPortReader::handleReadyRead()
{
std::cout << "handleReadyRead()" << std::endl;
m_readData.append(serialPort->readAll());
if (!m_timer.isActive())
m_timer.start(5000);
}
/*
void SerialPortReader::handleTimeout()
{
std::cout << "handleTimeout()" << std::endl;
if (m_readData.isEmpty()) {
std::cout << "No data was currently available for reading" << std::endl;
} else {
std::cout << "Data successfully received" << std::endl;
//m_standardOutput << m_readData << Qt::endl;
}
//QCoreApplication::quit();
}
void SerialPortReader::handleError(QSerialPort::SerialPortError serialPortError)
{
std::cout << "handleError()" << std::endl;
if (serialPortError == QSerialPort::ReadError) {
std::cout << "An I/O error occurred while reading" << std::endl;
//QCoreApplication::exit(1);
}
}
*/
SerialPortReader::~SerialPortReader() {
close();
}
// Close the files, filestreams, etc
void SerialPortReader::close() {
// ...
}
... and in my QApplication code you just need to include the .h and write this to instantiate the serial listener:
SerialPortReader *serialPortReader = new SerialPortReader(this);

Segmentation fault threads

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?

How can I run miltiple ServerApplications with POCO C++?

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. 😂

Multi clients not working properly on Qt4 Multi thread server?

Friends! I have written a code for a multi threaded TCP server in Qt4. The server is constantly listening for remote client connection requests. Whenever the client connects to the server, it takes its IP, Name and Port number and verifies if it is a recognized (authorized) client (that can be checked through a pre-stored text file having names, IPs and port numbers of all registered clients). If it is, the communication will proceed. Otherwise, the server terminates the connection.
EDIT1: here is the excerpt from myThread.cpp
void MyThread::run()
{
// Thread starts here
qDebug() << socketDescriptor << ("Starting thread...");
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor))
{
emit error(socket->error());
return;
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection);
qDebug() << socketDescriptor << ("Client connected!");
exec();
}
ISSUE: Now the problem is when I run the program and connects the first client it works fine. But as soon as the 2nd client is connected (testing through telnet, for now) it starts behaving strange (no messages receiving from client 2 or client 2 completely freezing etc). Can someone test the code in their machine?
myserver.cpp
#include "myserver.h"
#include "ioprogram.h"
#include <QTcpSocket>
#include <string>
#include <iostream>
using namespace std;
MyServer::MyServer(QObject *parent): QTcpServer(parent)
{
QStringList accepted_ip_list; //List of remote IPs that can be accepted in QString list format
accepted_ip_list.append("127.0.0.1"); // IPv4 local address
accepted_ip_list.append("::1"); // IPv6 local address
accepted_ip_list.append("172.18.48.139");
// Convert from QString to integer format, generating new list
foreach (const QString &ip, accepted_ip_list)
{
QHostAddress host_address(ip);
my_accepted_ip_list.append(host_address);
}
/*
myserver = new QTcpServer(this);
connect(myserver, &QTcpServer::incomingConnection, this, &MyServer::incomingConnection);
myserver->listen(QHostAddress::Any, 1234);
*/
}
void MyServer::startServer()
{
if(!this->listen(QHostAddress::Any,1234))
{
qDebug() << "Could not start server.";
}
else
{
qDebug() << "Listening...";
}
}
void MyServer::incomingConnection(qintptr socketDescriptor)
{
QTcpSocket *socket = new QTcpSocket(this);
socket->setSocketDescriptor(socketDescriptor);
qDebug() << socketDescriptor << "Connecting...";
QHostAddress host_address = socket->peerAddress();
//quint32 ipv4 = host_address.toIPv4Address();
std::string ipv4 = host_address.toString().toStdString();
QByteArray ipv6 = QByteArray((char*)host_address.toIPv6Address().c, 16);
IOProgram test;
bool status= test.checkAuthenticity(ipv4);
if(status == false){
/*
while (myserver->hasPendingConnections())
{
QTcpSocket *socket = myserver->nextPendingConnection();
QHostAddress host_address = socket->peerAddress();
bool contains = false;
*/
for(int i=0; i < my_accepted_ip_list.size(); i++)
{
//quint32 accepted_ipv4 = my_accepted_ip_list[i].toIPv4Address();
std::string accepted_ipv4 = my_accepted_ip_list[i].toString().toStdString();
if(accepted_ipv4 == ipv4)
{
status = true;
qDebug() << "testing...";
break;
}
/* else
{
qDebug() << "Rejected!";
socket->abort(); // Reject peer by disconnecting it
socket->deleteLater(); // Schedule the socket removal from memory
}
*/
/*if(my_accepted_ip_list[i].isEqual(host_address,QHostAddress::ConvertV4MappedToIPv4))
{
contains = true;
break;
}*/
}
if(!socket->QTcpSocket::ConnectedState){
socket->abort(); // Reject peer by disconnecting it
socket->deleteLater(); // Schedule the socket removal from memory
}
if(status)
{
qDebug() << "Accepted!";
MyThread *thread = new MyThread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
}
}
ioprogram.cpp
#include "ioprogram.h"
#include <QFile>
#include <QDebug>
#include <QTextStream>
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
struct Data {
string Name;
string IP;
string Port;
};
vector<Data> AllData;
IOProgram::IOProgram()
{
}
void Read()
{
QFile file("C:/Users/Shahwani/Documents/Bremen/Sem3/Qt/MultiServerAugust/NodesList.txt");
if(file.open(QIODevice::ReadWrite | QIODevice::Text))
{
QTextStream stream(&file);
QString line;
do
{
line = stream.readLine();
qDebug() << line;
}while(!line.isNull());
file.close();
}
}
string IOProgram::inpop()
{
ifstream inFile;
inFile.open("NodesList.txt");
// inFile.clear();
// Check for error
if(inFile.fail()){
cerr << "Error opening file" << endl;
exit(1);
}
int count = 0;
string line;
char delim = '\t';
getline (inFile,line);
// Read the file until the end
while(!inFile.eof())
{
getline (inFile,line);
string token;
stringstream stream(line); // Splitting a string using a delimiter
vector<string> vect;
while(getline(stream, token, delim) )
{
vect.push_back(token);
}
Data d;
d.Name = vect[0];
d.IP = vect[1];
d.Port = vect[2];
vect.clear();
AllData.push_back(d);
count++;
}
cout << count << " nodes found!" << endl;
inFile.close();
// Check for authenticity and only allow the recognised IPs
// Write the active nodes in a separate file on the disk
ofstream outFile;
outFile.open("sample.txt");
Data activeList;
for(int i = 0; i < AllData.size(); i++)
{
activeList = AllData[i];
outFile << "Name: " << activeList.Name << "\tIP: " << activeList.IP << "\tPort: " << activeList.Port <<endl;
}
outFile.close();
return activeList.IP;
}
bool IOProgram::checkAuthenticity(string ip)
{
for(int i=0;i<AllData.size();i++)
{
Data check;
check = AllData[i];
if(ip == check.IP)
{
return true;
}
else
{
return false;
}
}
}
I guess I cannot put a lot of code in one question. Let me know in case someone needs rest of the files like mythread.cpp or header files to understand the issue and how I can share them.