Qt C++ Console Server, Wait for socket connection & accept input at same time? - c++

I am writing a server as a Qt console application. I have the server set up to wait for a socket connection, but I also need to allow a user to input commands into the server for managing it. Both are working independently. However, the problem I ran into is that when I'm in a while loop accepting and processing input commands, the server doesn't accept connections.
I have a Socket class, and in its constructor, I have:
connect(server,SIGNAL(newConnection()),this, SLOT(newConnection()));
Right under that in the constructor, I call a function that has a more in-depth version of this for getting commands from the user:
QTextStream qin(stdin, QIODevice::ReadOnly);
QString usrCmd;
while(usrCmd != "exit" && usrCmd != "EXIT") {
//Get command input and process here
}
Inside newConnection(), I just accept the next connection and then use the socket.
QTcpSocket *serverSocket = server->nextPendingConnection();
How can I make it so the socket can wait for connections and wait for user-inputed commands at the same time?

Problem with your code is because you are blocking event loop with your while loop. So, the solution to your problem is to read from stdin asynchronously. On Linux (and on Mac, I guess), you can use QSocketNotifier to notify when the data is arrived on stdin, and to read it manually), as per various internet sources.
As I am using Windows, I would suggest you to do it in this way (which should work on all platforms):
Open the thread for reading data from stdin
Once you get some data (perhaps line?) you can use Qt signal-slot mechanism to pass the data to main thread for processing without blocking the event loop.
So, this is the pseudocode. MainAppClass should your existing server class, just edit the constructor to create new thread, and add new slot for processing the data.
class Reader: public QThread
{
Q_OBJECT
public:
Reader(QObject * parent = 0 ): QThread(parent){}
void run(void)
{
forever{
std::string data;
std::getline (std::cin, data);
if(data == "exit")
{
emit exitServer();
return;
}
emit dataReady(QString::fromStdString(data));
}
}
signals:
void dataReady(QString data);
void exitServer();
};
class MainAppClass: public QObject
{
Q_OBJECT
public:
MainAppClass()
{
Reader * tr = new Reader(this);
connect(tr, SIGNAL(dataReady(QString)), this, SLOT(processData(QString)));
connect(tr, SIGNAL(exitServer()), this, SLOT(exitServer()));
tr->start();
}
public slots:
void processData(QString data)
{
std::cout << "Command: " << data.toStdString() << std::endl;
}
void exitServer()
{
std::cout << "Exiting..." << std::endl;
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainAppClass myapp; //your server
app.exec();
return 0;
}
Since I wrote simple guidelines how to use QTcpSocket, here is the brief
When you get client QTcpSocket, connect readyRead() signal to some slot, and read data from sender() object. You don't need to read anything in the constructor.
For reading you can use standard QIODevice functions.
Note: this is pseudo code, and you may need to change few things (check the state of the stream on reading, save pointer to sockets in some list, subscribe to disconnected() signal, call listen() in constructor, check if QTcpServer is listening, etc).
So, you need to have slot onReadyRead() in your class which will have the following code:
void Server::readyReadSlot()
{
QTcpSocket *client = (QTcpSocket*)sender(); // get socket which emited the signal
while(client->canReadLine()) // read all lines!
// If there is not any lines received (you may not always receive
// whole line as TCP is stream based protocol),
// you will not leave data in the buffer for later processing.
{
QString line = client->readLine();
processLine(line); // or emit new signal if you like
}
}
Inside newConnection() you need to connect readyRead() signal with your slot.
void Server::newConnection()
{
QTcpSocket *clientSocket = server->nextPendingConnection();
connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
}

Related

Handling multiple connections using QThreadPool

Consider a situation where you need to maintain 256 tcp connections with devices just for ocassionally sending commands. I want to do this in parallel(It needs to block until it gets the response), I'm trying to use QThreadPool for this purpose but I have some doubts if it is possible.
I tried to use QRunnable but I'm not sure how sockets will behave between threads (sockets should be used only in thread that they were created in?)
I'm also worried about efficiency of this solution, I would be glad if somebody could propose some alternatives, not necessarily using QT.
Below I'm posting some snippets of the code.
class Task : public QRunnable {
Task(){
//creating TaskSubclass instance and socket in it
}
private:
TaskSubclass *sub;
void run() override {
//some debug info and variable setting...
sub->doSomething( args );
return;
}
};
class TaskSubclass {
Socket *sock; // socket instance
//...
void doSomething( args )
{
//writing to socket here
}
}
class MainProgram : public QObject{
Q_OBJECT
private:
QThreadPool *pool;
Task *tasks;
public:
MainProgram(){
pool = new QThreadPool(this);
//create tasks here
}
void run(){
//decide which task to start
pool->start(tasks[i]);
}
};
My favorite solution for this problem is by multiplexing your sockets using select(). That way you don't need to create additional threads, and it is a "very POSIX" way to do it.
See for example see this tutorial:
http://www.binarytides.com/multiple-socket-connections-fdset-select-linux/
Or a related question in:
Using select(..) on client
As OMD_AT has allready pointed out the best solution is to use Select() and let the kernel do the job for you :-)
here you have an example of an Async approach and an Syncron multi thread approach.
In this example we create 10 connection to a google webservice and make a simple get request to the server, we measure how long all connections in each approach needed to receive the response from the google server.
Be aware that you should use a more faster webserver to make a real test, like the localhost because the network latency has a big impact on the result.
#include <QCoreApplication>
#include <QTcpSocket>
#include <QtConcurrent/QtConcurrentRun>
#include <QElapsedTimer>
#include <QAtomicInt>
class Task : public QRunnable
{
public:
Task() : QRunnable() {}
static QAtomicInt counter;
static QElapsedTimer timer;
virtual void run() override
{
QTcpSocket* socket = new QTcpSocket();
socket->connectToHost("www.google.com", 80);
socket->write("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n");
socket->waitForReadyRead();
if(!--counter) {
qDebug("Multiple Threads elapsed: %lld nanoseconds", timer.nsecsElapsed());
}
}
};
QAtomicInt Task::counter;
QElapsedTimer Task::timer;
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
// init
int connections = 10;
Task::counter = connections;
QElapsedTimer timer;
/// Async via One Thread (Select)
// handle the data
auto dataHandler = [&timer,&connections](QByteArray data) {
Q_UNUSED(data);
if(!--connections) qDebug(" Single Threads elapsed: %lld nanoseconds", timer.nsecsElapsed());
};
// create 10 connection to google.com and send an http get request
timer.start();
for(int i = 0; i < connections; i++) {
QTcpSocket* socket = new QTcpSocket();
socket->connectToHost("www.google.com", 80);
socket->write("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n");
QObject::connect(socket, &QTcpSocket::readyRead, [dataHandler,socket]() {
dataHandler(socket->readAll());
});
}
/// Async via Multiple Threads
Task::timer.start();
for(int i = 0; i < connections; i++) {
QThreadPool::globalInstance()->start(new Task());
}
return app.exec();
}
Prints:
Multiple Threads elapsed: 62324598 nanoseconds
Single Threads elapsed: 63613967 nanoseconds
Although, the answer is already accepted, I would like to share my)
What I understood from your question: Having 256 currently active connections, from time to time you send a request ("command" as you named it) to one of them and wait for the response. Meanwhile, you want to make this process multithreaded and, though you said "It needs to block until it gets the response", I assume you implied blocking a thread which handles request-response process, but not the main thread.
If I indeed understand the question right, here is how I suggest to do it using Qt:
#include <functional>
#include <QObject> // need to add "QT += core" in .pro
#include <QTcpSocket> // QT += network
#include <QtConcurrent> // QT += concurrent
#include <QFuture>
#include <QFutureWatcher>
class CommandSender : public QObject
{
public:
// Sends a command via connection and blocks
// until the response arrives or timeout occurs
// then passes the response to a handler
// when the handler is done - unblocks
void SendCommand(
QTcpSocket* connection,
const Command& command,
void(*responseHandler)(Response&&))
{
const int timeout = 1000; // milliseconds, set it to -1 if you want no timeouts
// Sending a command (blocking)
connection.write(command.ToByteArray()); // Look QByteArray for more details
if (connection.waitForBytesWritten(timeout) {
qDebug() << connection.errorString() << endl;
emit error(connection);
return;
}
// Waiting for a response (blocking)
QDataStream in{ connection, QIODevice::ReadOnly };
QString message;
do {
if (!connection.waitForReadyRead(timeout)) {
qDebug() << connection.errorString() << endl;
emit error(connection);
return;
}
in.startTransaction();
in >> message;
} while (!in.commitTransaction());
responseHandler(Response{ message }); // Translate message to a response and handle it
}
// Non-blocking version of SendCommand
void SendCommandAsync(
QTcpSocket* connection,
const Command& command,
void(*responseHandler) (Response&&))
{
QFutureWatcher<void>* watcher = new QFutureWatcher<void>{ this };
connect(watcher, &QFutureWatcher<void>::finished, [connection, watcher] ()
{
emit done(connection);
watcher->deleteLater();
});
// Does not block,
// emits "done" when finished
QFuture<void> future
= QtConcurrent::run(this, &CommandSender::SendCommand, connection, command, responseHandler);
watcher->setFuture(future);
}
signals:
void done(QTcpSocket* connection);
void error(QTcpSocket* connection);
}
Now you can send a command to a socket using a separate thread taken from a thread pool: under the hood QtConcurrent::run() uses the global instance of QThreadPool provided by Qt for you. That thread blocks until it gets a response back and than handles it with responseHandler . Meanwhile, your main thread managing all your commands and sockets stays unblocked. Just catch done() signal which tells that response was received and handled successfully.
One thing to note: asynchronous version sends request only when there is a free thread in the thread pool and waits for it otherwise. Of course, that is the behavior for any thread pool (that is exactly the point of such pattern) but just do not forget about that.
Also I was writing code without Qt in handy so may contain some errors.
Edit: As it turned out, this is not thread safe as sockets are not reentrant in Qt.
What you can do about it is to associate a mutex with a socket and lock it each time you execute its function. This can be done easily creating a wrapper around QTcpSocket class. Please, correct me if I wrong.

QTCPSocket start by timer at the same time

I have problem with synchronize(start at the same time QTCPSocket) in my application I have 10 sockets. I have to read data at the similar time to all sockets. At this moment I have something that:
///...///
if(!socket->waitForConnected(-1))
{
qDebug() << "Server not found";
emit serverNotFound();
}else if(socket->state()==QAbstractSocket::ConnectedState){
qDebug() << "Connected"
connect(timer, SIGNAL(timeout()),this,SLOT(connected()));
timer->start(1000);
}
}
On connected signal:
void SocketsClass::connected()
{
sendRequest(socket, messageToServer);
}
The problem is that when the first socket get connected the timer starts for the one.
You can invert your approach. Don't wait for the sockets to get connected. Instead, check if the socket is connected in the slot activated by the timer. In that slot, you can iterate over all sockets and send the message to each of them.
Finally, you should never use Qt's waitForXxx methods, they lead to a horrible pseudo-synchronous code that is very error prone and hard to extend and maintain. Use the signal-slot mechanism instead.
Example:
SocketManager : public QObject {
Q_OBJECT
QTcpSocket m_sockets[10];
QTimer m_timer;
public:
SocketManager(QObject * parent = 0) : QObject(parent) {
... // connect all sockets here
m_timer.start(1000);
connect(&m_timer, &QTimer::timeout, [this]{
for (auto & socket : m_sockets)
if (socket.state() == QAbstractSocket::ConnectedState)
sendRequest(socket, messageToServer);
});
}
};

wait for data arrive from serial port in Qt

I use serial port connection in my qt application.
My problem- I cant get back the control (or the values comes from the comm port) after sending the command.
I have a class named serial.cpp which responsible to serial port connection.
This class contains 2 queues. one for save bytes from the comm port and second for the decoded messages. the class has the functions below:
void Serial::sendCommand(QString s)
{
QString sometext = s;
QByteArray ba = QByteArray::fromHex(sometext.toLatin1());
serial->write(ba);
}
void Serial::serialReceived()
{
QByteArray ba ;
serialArray = serial->readAll();
for (int i=0; i<sizeof(serialArray);i++)
{
queueBytes.enqueue(serialArray[i]); // queue for saving the bytes
}
QVector<int> vect = queueBytes.toVector();
packetSize = 6;
if (vect.size() >= packetSize)
{ // the whole packet arrived
for (int i =0 ;i<packetSize;i++)
{
item = queueBytes.dequeue();
ba.append(item);
}
}
if (ba.toHex() == "12ee02010176")
queueMsgs.enqueue("ACK");
// ... and so on
}
here is the call class:
void Engine::onNewMessageFromAppReceived(int msgId,QString args)
{
serial->sendCommand("ee1203190209005569");
while (serial->queueMsgs.size() == 0) // infinite loop-the queue is always empty
{
usleep(1);
}
QVector<QString> vect2 = serial->queueMsgs.toVector();
qDebug() << vect2 << "get ack---" ;
}
please your help
The QSerialPort class inherits from QIODevice which has waitFor... methods that may be what you're looking for. Take a look at these docs.
If you want to handle the serial port asynchronously, use the readyRead signal and perform reading in a function that you connected to that signal. If you don't mind that the operation is blocking, the waitForReadyRead function is what you're looking for.
The good way
Here's the proper way to do it using Qt's signals and slots mechanism. This will not block your GUI and lets your application respond to user actions even while you are waiting for the serial port.
Connect a function to the bytesWritten signal
The code you want to execute after you sent data through the serial port should be placed in this function.
Connect a function to the readyRead signal
The code you want to execute after you read some data from the serial port should be placed in this function.
Open the port
The bad way
In some cases you can do it like this, but it's blocking, meaning that your GUI will freeze while your app is waiting for the serial port. I don't recommend doing it like this.
Open the port
Send data
Call waitForBytesWritten
Call waitForReadyRead
Working example code
Qt has a vast amount of working example code. There are even examples about how to use QSerialPort, and they are well worth checking out. You might be most interested in the async writer example and the async reader example.

Qt QTcpSocket() readReady Signal never fires (slot never called) in multithreaded Server applicaton. waitForReadyRead() method works fine

I'm writing a threaded TcpServer (each client in its own thread) using QTcpServer and QTcpSocket. The client application works correctly and sends data every 3 seconds but the readReady() signal never fires, meaning my receive_data() function is never called. When using socket->waitForReadyRead() and calling receive_data() by myself everything works fine. Please have a look at the code below, maybe I made some mistake with the moveToThread / connect functionality Qt offers.
Client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <QThread>
#include <QTcpSocket>
#include <QHostAddress>
#include "PacketDefinitions.h"
#include "tcpserver.h"
class Client : public QObject
{
Q_OBJECT
public:
explicit Client(int socket,TcpServer *parent,bool auto_disconnect = true);
~Client();
bool isGameServer(){return is_gameserver;}
GameServerPacket getGameServerData(){return gameserver;}
void run();
private:
QTcpSocket* client;
TcpServer *parent_server;
int socket;
GameServerPacket gameserver;
ClientPacket clientdata;
bool is_gameserver;
bool auto_disconnect;
QHostAddress client_ip;
quint16 client_port;
signals:
void disconnected(Client *);
private slots:
void remove_from_clientlist();
void receive_data();
void display_error(QAbstractSocket::SocketError error);
};
#endif // CLIENT_H
Client.cpp
#include "client.h"
#include "PacketDefinitions.h"
#include "time.h"
#include <iostream>
Client::Client(int _socket, TcpServer *parent,bool _auto_disconnect)
{
auto_disconnect = _auto_disconnect;
parent_server = parent;
is_gameserver = false;
socket = _socket;
}
void Client::run(){
client = new QTcpSocket();
if(client->setSocketDescriptor(socket) == false){
std::cout << client->errorString().toStdString() << std::endl;
remove_from_clientlist();
return;
}
connect(client,SIGNAL(disconnected()),this,SLOT(remove_from_clientlist()));
if(connect(client,SIGNAL(readyRead()),this,SLOT(receive_data()),Qt::DirectConnection) == false) return;
connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(display_error(QAbstractSocket::SocketError)));
client_ip = client->peerAddress();
client_port = client->peerPort();
std::cout << "New incomming connection " << client->peerAddress().toString().toStdString() << ":" << client->peerPort() << std::endl;
//this works fine
// while(client->waitForReadyRead()){
// receive_data();
// }
}
void Client::receive_data(){
QDataStream stream(client);
stream.setVersion(QDataStream::Qt_5_2);
quint32 magic; stream >> magic;
//interpret data
if(magic == GAMESERVER_MAGIC){
is_gameserver = true;
gameserver.Read(stream);
gameserver.port = client_port;
gameserver.ip = client_ip;
time(&(gameserver.last_update));
parent_server->add_server(gameserver.ip.toString(),gameserver);
std::cout << "GameServer " << gameserver.name << " registerd" << std::endl;
}else if(magic == CLIENT_MAGIC){
is_gameserver = false;
clientdata.Read(stream);
//get nearby servers
GameServerListPacket server_list = parent_server->getServerList(clientdata);
QDataStream outstream(client);
server_list.Write(outstream);
std::cout << "Sending ServerList(" << server_list.server_count << ") to " << client->peerAddress().toString().toStdString() << std::endl;
if(auto_disconnect){
//client->flush();
client->waitForBytesWritten();
}
}else{
std::cout << "Unknown package " << magic << std::endl;
}
//not enough data read, somthing is wrong, just for debugging
if(client->bytesAvailable()> 0) std::cout << "BytesAvailable " << client->bytesAvailable() << std::endl;
if(auto_disconnect) remove_from_clientlist();//close the connection once the serverlist was deployed
}
In the TcpServer.cpp add_client() is called when newConnection() was emitted by the QTcpServer:
void TcpServer::add_client(){
while(server->hasPendingConnections()){
QTcpSocket *socket = 0;
if(thread_pool.size() < max_connections && (socket = server->nextPendingConnection())){
QThread *thread = new QThread();
Client * client = new Client(socket->socketDescriptor(),this,auto_disconnect);
client->moveToThread(thread);
client->run();
thread->start();
connect(client,SIGNAL(disconnected(Client*)),this,SLOT(remove_client(Client*)));
WRITELOCK(thread_pool.insert(client,thread));
}
}
}
the order calling client->run() and thread->start() doesn't seem to matter. Some time ago the code (not this exact code) worked fine but I can't remember what I changed that made it fail. Any help is appreciated!
Thanks in advance
Fabian
Edit 1:
I derived from QTcpServer and reimplemented void incomingConnection(qintptr socketDescriptor) which works fine. I dont use QThreadPool, its just a QMap and remove_client(Client*) closes the QTcpSocket and stops the thread and removes it from the map. Everything works fine on linux, on windows I get the following error: QSocketNotifier: socket notifiers cannot be disabled from another thread ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread....
Caused by this remove_client(Client*)
void TcpServer::remove_client(Client *client){
//disconnect(client,SIGNAL(disconnected(Client*)),this,SLOT(remove_client(Client*)));
lock.lockForWrite();
QMap<Client*,QThread*>::iterator itr = thread_pool.find(client);
if(itr != thread_pool.end()){
//delete itr.key(); causes the problem on windows
itr.value()->quit();
itr.value()->wait();
delete itr.value();
thread_pool.erase(itr);
}
lock.unlock();
}
Where and how should I free the Client object? If i'd use QThreadPool theres no way to iterate through the clients in case i want to send a message to more than one client. I could use a list/map holding only the Client* but then QThreadPool might delete them for me right before i want to access it. Any suggestions?
There is a problem with how you move your client object to a new thread. Actually, Client::run executes in the same thread as TcpServer::add_client.
Also QTcpSocket client remains in the default thread, while its container (Client class) is moved to a new thread. That's why the connection with Qt::DirectConnection type doesn't work.
Try this:
class Client : public QObject
{
Q_OBJECT
...
public slots:
void run();
...
}
Client::Client(int _socket, TcpServer *parent,bool _auto_disconnect)
{
...
client = new QTcpSocket(this);
}
void Client::run()
{
...
connect(client, SIGNAL(readyRead()), this, SLOT(receive_data()));
...
}
And here's how you should move your client to a new thread:
void TcpServer::add_client()
{
...
QThread *thread = new QThread();
Client * client = new Client(socket->socketDescriptor(),this,auto_disconnect);
client->moveToThread(thread);
connect(thread, SIGNAL(started()), client, SLOT(run()));
thread->start();
...
}
There are a number of things wrong with your code.
1.You have two QTcpSocket object trying to collect data from the same underlying socket descriptor. You appear to use the first one only to get access to the socket descriptor value which you then pass to your Client class. You might end up losing data because you won't be able to tell which socket will be getting what data from the operating system.
If you are creating a derived class of QTcpServer, rather reimplement QTcpServer::incomingConnection(qintptr socketDescriptor) instead of your existing TcpServer::add_client() function. Since this protected function is called once for every new connection, you don't need to make any connections to the newConnection() signal, nor do you have to loop while new connections are pending. You will also then only have one QTcpSocket connected to each socket descriptor so you won't lose data.
2.You seem to be using QThreadPool to manage threads. If you make Client a derived class of QRunnable (take not that with multiple inheritance of QObject, QObject must always be first), you don't need to check the maximum connections and you can eliminate all the QThread boiler-plating.
Taking 1. and 2. into account, your TcpServer::add_client() function will be replaced with:
void TcpServer::incomingConnection(qintptr socketDescriptor){
Client * client = new Client(socketDescriptor,this,auto_disconnect);
connect(client,SIGNAL(disconnected(Client*)),this,SLOT(remove_client(Client*)));
QThreadPool::globalInstance()->start(client);
}
With QThreadPool, there's no need to check whether the max number of threads has been reached or not. If the maximum has been reached, any new calls to start() will queue the next connection until a thread becomes available.
3.The reason your socket is not reading any data unless you call waitForReadyRead() is because you're executing the run() function in the main thread, creating the local socket in the main thread, you make a DirectConnection with the instance of Client and then move client to a different thread. You cannot have direct connections between threads.
You will need to add a local QEventLoop to your run() function to handle all events and signals of your new thread but remember to connect signals to your loop's quit() slot so the run() function will exit, otherwise your thread will continue to run forever.

Qt QUdpSocket: readyRead() signal and corresponding slot not working as supposed

I have problems to find why my short QUdpSocket example is not working. I plan to use only one UDP socket to read and write to an embedded device at 192.168.2.66 on port 2007. The device will reply always on port 2007 to the sender. I tested the device with an UDP terminal software and works as I said. So, I designed a simple class to embed the functions needed to manage the device:
class QUdp : public QObject
{
// Q_OBJECT
public:
explicit QUdp(QObject *parent = 0, const char *szHost = 0, uint16_t wPort = 0);
~QUdp();
bool Open();
int64_t Write(QByteArray &data);
int64_t Write(QString strData);
private:
QString m_strHost;
uint16_t m_wPort;
QUdpSocket *OUdp;
private slots:
void received();
};
I suppose that the problem is in the Open method:
bool QUdp::Open()
{
QHostAddress OHost;
connect(OUdp, &QUdpSocket::readyRead, this, &QUdp::received);
bool zRet = OUdp->bind(QHostAddress::AnyIPv4, m_wPort, QUdpSocket::ShareAddress);
OHost.setAddress(m_strHost);
OUdp->connectToHost(OHost, m_wPort, QIODevice::ReadWrite);
return(zRet);
}
//------------------------------------------------------------------------
I used the Qt 5 syntax for the connect(), m_strHost value is "192.168.2.66" and m_wPort is 2007
my Write method is very simple (the part inside #if 0 was added to see if the socket received any data)
int64_t QUdp::Write(QString strData)
{
QByteArray data(strData.toStdString().c_str(), strData.length());
int64_t iCount = OUdp->write(data);
#if 0
bool zRecved = OUdp->waitForReadyRead(3000);
int64_t iRecvCount = OUdp->bytesAvailable();
#endif
return(iCount);
}
//------------------------------------------------------------------------
and this is my test received() method... I wrote it just to see if the signal-slot works or not:
void QUdp::received()
{
int64_t iRecvCount = OUdp->bytesAvailable();
}
//------------------------------------------------------------------------
I don't understand what is wrong.. I found some posts saying that is not possible read and write using only one UDP socket in Qt (Qt uses BSD sockets so it should be possible) but my example looks as the proposed solutions so I really don't understand what is not working.
You can read and write using just one UDP socket in Qt. I have this running in Qt5 on both windows and Linux, so no worries there :)
To establish Rx direct comms in QUdpSocket you should really use the bind() function, something like this:
// Rx connection: check we are not already bound
if (udpSocket->state() != udpSocket->BoundState)
{
// Rx not in bound state, attempt to bind
udpSocket->bind(address, port);
}
Once this has completed you will be able to check that udpSocket->state() == udpSocket->BoundState is true, then you are successfully "bound" to this ip/port. Now your listening can begin if your connection to readready() is correct. I have not used this connection syntax that you are using, so I can't say much about that, but here is the example of how I connect:
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(rxDataEvent()), Qt::QueuedConnection);
Where "this" is the class which contains my QUdpSocket and udpSocket is a QUdpSocket pointer. Then rxDataEvent is defined below:
void CIpComms::rxDataEvent(void)
{
QByteArray rxData;
QHostAddress sender;
quint16 senderPort;
while (udpSocket->hasPendingDatagrams())
{
// Resize and zero byte buffer so we can make way for the new data.
rxData.fill(0, udpSocket->pendingDatagramSize());
// Read data from the UDP buffer.
udpSocket->readDatagram(rxData.data(),
rxData.size(),
&sender,
&senderPort);
// Emit ipDataReceived Signal
emit ipDataReceived(rxData);
}
}
Here we continually check for datagrams until there are none pending (bit easier then doing the whole "bytesAvailable thing") and stick the data into a QByteArray and emit it off elsewhere (which you obviously don't have to do!).
That is all you need to do for connection. Then to send is very easy, you simply have to call writeDatagram(), well there are other options but this is by far the easier to use:
if (-1 == udpSocket->writeDatagram(txData, address, port))
{
// Data write failed, print out warning
qWarning() << "Unable to write data to " << address.toString() << ":" << port << endl;
return false;
}
I have pretty much cut and pasted this from my working code (with a few edits to keep it short-n-simple so it should give you a starting point. In summary where I believe you are going wrong is that you have not "bound" to the IP address/port and are therefore NOT listening to it and will not receive any readReady() events.