Dequeue always fails, queue is always empty - qt

I do not know what the heck is wrong with my code that it never Dequeus the queue, instead isEmpty always meets true.
class ConcurrentQueue
{
private:
QQueue<QByteArray> dataStore;
public:
void Enqueue(QByteArray value);
QByteArray Dequeue();
bool isEmpty();
private:
QMutex mutex;
};
void ConcurrentQueue::Enqueue(QByteArray value)
{
qDebug() << dataStore.length();
mutex.lock();
dataStore.enqueue(value);
mutex.unlock();
qDebug() << dataStore.length();
}
QByteArray ConcurrentQueue::Dequeue()
{
// mutex.lock();
// return dataStore.dequeue();
// mutex.unlock();
QByteArray tmp;
mutex.lock();
if(!dataStore.isEmpty())
{
tmp = dataStore.dequeue();
}
mutex.unlock();
return tmp;
}
bool ConcurrentQueue::isEmpty()
{
return dataStore.isEmpty();
}
next a timer is connected to a slot to Enqueu a packet every lt's say 10 milliseconds:
QByteArray built((char*)data, len) ;
//qDebug() << built.toHex();
qDebug() << "EnQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ";
queue.Enqueue(built);
A thread regularly checks if this queue is not empty it dequeues the queue and does something, but isEmplty always returns true
if(queue.isEmpty())
{
qDebug() << "#####################################";
return;
}
//NEVER COMES HERE
QByteArray rd15Bytes = queue.Dequeue();
here's the thread:
Write::Write()
{
}
void Write::run(){
while(1)
{
rs.writeToSerialPort(); // in this function above always isemplty is true
this->msleep(10);
}
}

Related

QTcpSocket how to return QString

I have a service: GWT client calls QT QTcpSocket function that make a request to a device and gets responses(it cannot be only the one response. I should waiting for all of them).
According to the QT documentation I can't use waitForReadyRead() function because I use Windows platform.
Note: This function may fail randomly on Windows. Consider using the
event loop and the readyRead() signal if your software will run on
Windows. http://doc.qt.io/qt-5/qabstractsocket.html#waitForReadyRead
I have only one decision now:
pseudo code:
QString MainQTFunc() {
create new thread;
while (!thread.isStopped()) {
sleep(x);
}
return QString variable from thread to GWT client;
}
New Thread {
run() {
make a TcpRequest to the device...
}
boolean isStopped() {
if(we got the response!!!) {
return true;
}
}
}
Does it the best solution to do so? I can't understand how to send simply QString variable after I get the result. Is it really impossible to the powerful QT?
Now I have(without any threads):
// The function should to return QString to the GWT client
QString MainWindow::TcpConnect(QByteArray data) {
_pSocket = new QTcpSocket( this );
connect( _pSocket, SIGNAL(readyRead()), SLOT(readTcpData()) );
connect( _pSocket, SIGNAL(connected()), SLOT(connected()) );
connect( _pSocket, SIGNAL(disconnected()), SLOT(disconnected()) );
dataGlobal = data;
_pSocket->connectToHost("IP", port);
//waiting here for all responses and sendinig the last response
return responseHexGlobal;
}
void MainWindow::connected() {
qDebug() << "connected. " << QDateTime::currentDateTime();
_pSocket->write( dataGlobal );
}
void MainWindow::disconnected() {
qDebug() << "disconnected. " << QDateTime::currentDateTime();
}
void MainWindow::readTcpData()
{
QByteArray data = _pSocket->readAll();
QByteArray as_hex_string = data.toHex();
QString response = QString(as_hex_string);
if(some condition here...) {
responseHexGlobal = response;
_pSocket->disconnectFromHost();
}
}
It's the best solution I've found. It works, but I don't like it
QString JSPrinter::connectTcp(QByteArray data) {
QTimer timer;
timer.setSingleShot(true);
QEventLoop loop;
_pSocket = new QTcpSocket( this ); // <-- needs to be a member variable: QTcpSocket * _pSocket;
connect( _pSocket, SIGNAL(readyRead()), SLOT(readTcpData()) );
connect( _pSocket, SIGNAL(connected()), SLOT(connected()) );
connect( _pSocket, SIGNAL(disconnected()), SLOT(disconnected()) );
connect( &timer, SIGNAL(timeout()), &loop, SLOT(quit()) );
loop.connect( this, SIGNAL(exitLoop()), SLOT(quit()) );
dataGlobal = data;
_pSocket->connectToHost(ip_, port_);
timer.start(75000);
loop.exec();
if(timer.isActive())
logger()->info("ok");
else
logger()->info("timeout");
return responseHexGlobal;
}
void JSPrinter::connected() {
qDebug() << "connected. " << QDateTime::currentDateTime();
_pSocket->write( dataGlobal );
}
void JSPrinter::disconnected() {
qDebug() << "disconnected. " << QDateTime::currentDateTime();
}
void JSPrinter::readTcpData() {
QByteArray data = _pSocket->readAll();
QByteArray as_hex_string = data.toHex();
std::string stdString(as_hex_string.constData(), as_hex_string.length());
qDebug() << "readTcpData response " << QDateTime::currentDateTime() << QString::fromStdString(stdString);
// doing something...
if(condition) {
responseHexGlobal = received;
qDebug() << "responseHexGlobal " << responseHexGlobal;
emit exitLoop();
_pSocket->disconnectFromHost();
} else {
emit exitLoop();
_pSocket->disconnectFromHost();
return;
}
}

QTcpSocket data arrives late

I am using QTCPSockets to talk to a program I've written in Qt for Raspberry Pi. The same software runs on my Mac (or Windows, whatever). The Pi is running a QTCPServer.
I send JSON data to it and most of the time this goes ok.
But sometimes, the Pi is not responding, the data does not seem to arrive. But then, when I send some more data, that data is not being handled, but the previous Json message is! And this stays like this. All the messages are now off by 1. Sending a new messages, triggers the previous one.
It feels a bit connected to this bugreport: https://bugreports.qt.io/browse/QTBUG-58262
But I'm not sure if it is the same.
I've tried waitForBytesWritten and flush and it seemed to work at first, but later I saw the issue again.
I expect that the TCP buffer on the Pi is not being flushed, but I do now know how to make sure that all data is handled right away.
As asked, here is some sourcecode:
This is the client software:
Client::Client() : tcpSocket(new QTcpSocket(this)), in(tcpSocket)
{
connect(tcpSocket, &QIODevice::readyRead, this, &Client::readData);
connect(tcpSocket, &QTcpSocket::connected, this, &Client::connected);
connect(tcpSocket, &QTcpSocket::stateChanged, this, &Client::onConnectionStateChanged);
void (QAbstractSocket:: *sig)(QAbstractSocket::SocketError) = &QAbstractSocket::error;
connect(tcpSocket, sig, this, &Client::error);
}
void Client::connectTo(QString ip, int port) {
this->ip = ip;
this->port = port;
tcpSocket->connectToHost(ip, port);
}
void Client::reconnect() {
connectTo(ip, port);
}
void Client::disconnect()
{
tcpSocket->disconnectFromHost();
}
void Client::connected()
{
qDebug() << TAG << "connected!";
}
void Client::error(QAbstractSocket::SocketError error)
{
qDebug() << TAG << error;
}
void Client::sendData(const QString& data)
{
bool connected = (tcpSocket->state() == QTcpSocket::ConnectedState);
if (!connected) {
qDebug() << TAG << "NOT CONNECTED!";
return;
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
out << data;
tcpSocket->write(block);
tcpSocket->flush();
}
void Client::sendData(const QByteArray& data) {
bool connected = (tcpSocket->state() == QTcpSocket::ConnectedState);
if (!connected) {
qDebug() << TAG << " is NOT connected!";
return;
}
tcpSocket->write(data);
tcpSocket->flush();
}
void Client::readData()
{
in.startTransaction();
QString data;
in >> data;
if (!in.commitTransaction())
{
return;
}
emit dataReceived(data);
}
void Client::onConnectionStateChanged(QAbstractSocket::SocketState state)
{
switch (state) {
case QAbstractSocket::UnconnectedState:
connectionState = "Not connected";
break;
case QAbstractSocket::ConnectingState:
connectionState = "connecting";
break;
case QAbstractSocket::ConnectedState:
connectionState = "connected";
break;
default:
connectionState = QString::number(state);
}
qDebug() << TAG << " connecting state: " << state;
emit connectionStateChanged(connectionState);
if (state == QAbstractSocket::UnconnectedState) {
QTimer::singleShot(1000, this, &Client::reconnect);
}
}
and here the server part:
Server::Server()
{
tcpServer = new QTcpServer(this);
connect(tcpServer, &QTcpServer::newConnection, this, &Server::handleConnection);
tcpServer->listen(QHostAddress::Any, 59723);
QString ipAddress;
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
// use the first non-localhost IPv4 address
for (int i = 0; i < ipAddressesList.size(); ++i) {
if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
ipAddressesList.at(i).toIPv4Address()) {
ipAddress = ipAddressesList.at(i).toString();
break;
}
}
// if we did not find one, use IPv4 localhost
if (ipAddress.isEmpty())
ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
qDebug() << TAG << "ip " << ipAddress << " serverport: " << tcpServer->serverPort();
}
void Server::clientDisconnected()
{
QTcpSocket *client = qobject_cast<QTcpSocket *>(QObject::sender());
int idx = clients.indexOf(client);
if (idx != -1) {
clients.removeAt(idx);
}
qDebug() << TAG << "client disconnected: " << client;
client->deleteLater();
}
void Server::handleConnection()
{
qDebug() << TAG << "incoming!";
QTcpSocket* clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection, &QAbstractSocket::disconnected, this, &Server::clientDisconnected);
connect(clientConnection, &QIODevice::readyRead, this, &Server::readData);
clients.append(clientConnection);
broadcastUpdate(Assets().toJson());
}
void Server::readData()
{
QTcpSocket *client = qobject_cast<QTcpSocket *>(QObject::sender());
QDataStream in(client);
in.startTransaction();
QString data;
in >> data;
if (!in.commitTransaction())
{
return;
}
...
// here I do something with the data. I removed that code as it is
// not necessary for this issue
...
broadcastUpdate(data);
}
void Server::broadcastUpdate(const QString& data)
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
out << data;
foreach(QTcpSocket* client, clients) {
bool connected = (client->state() == QTcpSocket::ConnectedState);
if (!connected) {
qDebug() << TAG << client << " is NOT connected!";
continue;
}
client->write(block);
}
}
I think the problem is with your void Client::readData(): you have to write it in such a way that you read all available data from the socket inside it (usually it's written with while (socket->bytesAvailable() > 0) { ... } loop).
It is because of the way the readyRead() signal is emitted: the remote peer may send any non-zero number of packets to you, and your socket will emit any non-zero number of readyRead() signals. In your case, it seems that the server sends two messages but they only cause one readyRead() signal to be emitted on the client.

How does QTcpSocket write data to client?

I wanna make a simple Qt app which can perform task like image below:
I have learnt Fortune Server examples and actually I want this app is just like the combination of Fortune Server and Fortune Client.
dialog.cpp
void Dialog::on_btnListen_clicked(bool checked)
{
if(checked)
{
listener = new ServerSock(this);
if(!listener->listen(QHostAddress::LocalHost,ui->boxPort->value()))
{
QMessageBox::critical(this,tr("Error"),tr("Cannot listen: %1").arg(listener->errorString()));
ui->btnListen->setChecked(false);
return;
}
else
{
qDebug() << "Server is listening to port" << listener->serverPort();
ui->btnListen->setText(tr("Listening"));
this->setWindowTitle(tr("Listening and Running"));
}
}
else
{
listener->close();
listener->deleteLater();
ui->tmbListen->setText(tr("Listen again"));
this->setWindowTitle(tr("Taking a rest"));
}
}
serversock.cpp:
#include "serversock.h"
ServerSock::ServerSock(QObject *parent) :
QTcpServer(parent)
{
}
void ServerSock::incomingConnection(int descriptor)
{
thread = new Threading(descriptor,this);
connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));
thread->start();
}
threading.cpp:
#include "threading.h"
Threading::Threading(int descriptor, QObject *parent) :
QThread(parent)
{
this->descriptorSocket = descriptor;
}
void Threading::run()
{
qDebug() << "Thread is started...";
socketThread = new QTcpSocket();
if(!socketThread->setSocketDescriptor(this->descriptorSocket))
{
emit error(socketThread->error());
return;
}
connect(socketThread,SIGNAL(readyRead()),this,SLOT(readyToRead()),Qt::DirectConnection);
connect(socketThread,SIGNAL(disconnected()),this,SLOT(unconnected()),Qt::DirectConnection);
qDebug() << descriptorSocket << "Connected";
exec(); //loop
}
void Threading::readyToRead()
{
QByteArray data = socketThread->readAll();
socketOut = new QTcpSocket();
socketOut->connectToHost("192.168.0.1",8080);
if(socketOut->waitForConnected(5000))
{
QByteArray query("GET http:// mysite. com/page HTTP/1.1\r\nHost: anothersite.com\r\r\r\n" + data); //example
socketOut->write(query);
socketOut->write("\r\r\r\n");
socketOut->waitForBytesWritten(1000);
socketOut->waitForReadyRead(3000);
outPut = socketOut->readAll();
if(socketOut->error() != socketOut->UnknownSocketError)
{
qDebug() << socketOut->errorString();
socketOut->disconnectFromHost();
this->quit();
socketThread->abort();
}
else
{
socketOut->close();
}
}
else
{
qDebug() << "Cannot connected";
}
if(!outPut.isNull())
socketThread->write(outPut);
qDebug() << descriptorSocket << " Data in: " << data;
void Threading::unconnected()
{
qDebug() << "Disconnected";
socketThread->abort();
exit(0);
deleteLater();
}
The problem is that I don't know how to return data from remote host to the local client, like the image below:
it sends request, but there is no response. How to accomplish this?

send Qevent from thread

Please can some-one suggest on this question..? I have to send data from my TX thread to mainwindow using class derived from QEvent.
I want my RX thread to throw an event whenever some data is received so hat i can display that data in the Mainwindow.
I start a main thread when button start is pressed. I save the pointer to my mainwindow inside the object of main thread. I will use this pointer to post events to the mainwindow object.
When first time i enter the Qthread function dowork_rx(). Event is thrown & i am able to catch it in customEvent() handler. But when dowork_rx() while loop starts when i throws the event it does not trigger the customEvent() function.
Please suggest how to resolve this problem.
My qevent class :---
//String event derived class
template <typename T> class StringEvent : public QEvent
{
QString m_str;
public:
explicit StringEvent(const QString val) : QEvent(staticType()), m_str(val)
{
}
void setvalue(QString val)
{
m_str = val;
}
QString value() const
{
return m_str;
}
static QEvent::Type staticType()
{
static int type = QEvent::registerEventType();
return static_cast<QEvent::Type>(type);
/*
static int type;
if(type == 0)
{
type = QEvent::registerEventType();
}
return static_cast<QEvent::Type>(type);*/
}
static bool is(const QEvent * ev)
{
return ev->type() == staticType();
}
};
class UpdateEvent : public StringEvent<UpdateEvent>
{
public:
explicit UpdateEvent(QString val): StringEvent(val)
{
//qDebug() << "hello";
}
};
class ClearEvent : public StringEvent<ClearEvent>
{
public:
explicit ClearEvent(QString val): StringEvent(val)
{
}
};
Dowork function of the thread :----
// Common slot for the rx - thread
void RxThreadObject::dowork_rx()
{
int i =0;
qDebug() << "\nrx start \n";
myUpdateEvent_rx = new UpdateEvent("UpdateEventObject - dowork_rx");
//myUpdateEvent_rx->setvalue("first");
QCoreApplication::postEvent(m_pMainThreadObj->ptrmainwindow, myUpdateEvent_rx);
qDebug() << "\nrx throw event - done \n";
while(!m_bQuitRx)
{
SleepTimerDelay::sleep(2);
if(i==0){
//qDebug() << "\nrx throw event - done 11 \n";
myUpdateEvent_rx = new UpdateEvent("first");
myUpdateEvent_rx->setvalue("first");
QCoreApplication::postEvent(m_pMainThreadObj->ptrmainwindow, myUpdateEvent_rx);
i++;
}else{
//qDebug() << "\nrx throw event - done 22 \n";
myUpdateEvent_rx = new UpdateEvent("second");
myUpdateEvent_rx->setvalue("second");
QCoreApplication::postEvent(m_pMainThreadObj->ptrmainwindow, myUpdateEvent_rx);
i=0;
}
}
qDebug() << "\nrx end \n";
}
Event handler :----
/*!
** Custom event handler
*/
void MainWindow::customEvent(QEvent *event)
{
qDebug() << "oo customEvent";
if (UpdateEvent::is(event)) {
UpdateEvent *tempUpdateEvent = static_cast<UpdateEvent *>(event);
qDebug() << tempUpdateEvent->value();
}
else if (ClearEvent::is(event)) {
ClearEvent *tempClearEvent = static_cast<ClearEvent *>(event);
qDebug() << tempClearEvent->value();
}
}
/*!
** event filter handler
*/
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
qDebug() << "oo eventFilter";
if (UpdateEvent::is(event)) {
UpdateEvent *tempUpdateEvent = static_cast<UpdateEvent *>(event);
qDebug() << tempUpdateEvent->value();
}
else if (ClearEvent::is(event)) {
ClearEvent *tempClearEvent = static_cast<ClearEvent *>(event);
qDebug() << tempClearEvent->value();
}
return true;
}

unable to establish two way communication using qt

I have used QTcpSocket and QTcpServer class of qt to establish two way communication. I am able to send data from client to server. But am not getting the response back from server i.e my client.cpp never fires readyRead() signal. I have checked using Wireshark that my data from the server is available in specifed port.
I am posting my client.cpp code( Please help) :
Client::Client(QObject* parent): QObject(parent)
{
socket = new QTcpSocket(this);
connect(socket, SIGNAL(connected()),
this, SLOT(startTransfer()));
connect(socket, SIGNAL(readyRead()),this, SLOT(startRead()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(socketError(QAbstractSocket::SocketError)) );
}
Client::~Client()
{
socket->close();
}
void Client::start(QString address, quint16 port)
{
addr.setAddress(address);
socket->connectToHost(addr,port,QTcpSocket::ReadWrite);
}
void Client::startTransfer()
{
printf("Connection established.\n");
char buffer[1024];
forever
{
printf(">> ");
gets(buffer);
int len = strlen(buffer);
buffer[len] = '\n';
buffer[len+1] = '\0';
socket->write(buffer);
socket->flush();
}
}
void Client::startRead()
{
cout<<"inside startRead()<<endl";
while(socket->canReadLine())
{
QByteArray ba = socket->readLine();
if(strcmp(ba.constData(), "!exit\n") == 0)
{
socket->disconnectFromHost();
break;
}
printf(">> %s", ba.constData());
}
}
void Client::socketError(QAbstractSocket::SocketError )
{
qDebug()<<"error" ;
}
Looks like you have forever loop here. This means that your Qt main eventloop never gets the control back after you call startTransfer(). How do you suppose the Qt should run the startRead() code if you block your execution thread with infinite loop?
For Amartel adding the server code:
Server::Server(QObject* parent): QObject(parent)
{
// cout << "Before connect" << endl;
connect(&server, SIGNAL(newConnection()),
this, SLOT(acceptConnection()));
cout << "Listening.." << endl;
server.listen(QHostAddress::Any, 9999);
// cout << "Server started.." << endl;
}
Server::~Server()
{
server.close();
}
void Server::acceptConnection()
{
// cout << "In acceptConnection" << endl;
client = server.nextPendingConnection();
connect(client, SIGNAL(readyRead()),
this, SLOT(startRead()));
}
void Server::startRead()
{
while(client->canReadLine())
{
QByteArray ba = client->readLine();
if(strcmp(ba.constData(), "!exit\n") == 0)
{
client->disconnectFromHost();
break;
}
printf(">> %s", ba.constData());
int result = 0;
bool ack = true;
result = client->write("I Reached");
cout<<result<<endl;
if(result <= 0)
qDebug("Ack NOT sent to client!!!");
else
qDebug("Ack sent to client.");
// client->write("I Reached");
client->flush();
}
}

Resources