I'm having trouble sending data from a server to a client using Qt. Whenever I do QTcpSocket::waitForBytesWritten() after a call to QTcpSocket::write(...), it returns false.
I tried using the bytesWritten signal, but that never gets emitted, presumably because no data is able to be written, and no data is received on the client side.
The writeData method is what is being called in the MainWindow class, but to try and narrow down the cause of the problem, I moved the writing of data to the client into the newConnection method.
The message Connection received is printed to the output window. I'm sending the string Some random data in the newConnection method to the client for testing purposes, but this is not being received by the client (the code to output the received data on the client side is inside Character::readData() method).
The value of the returnValue variable is true, and the code returns from the call to the client->waitForBytesWritten(-1) method. client->errorString() gives Unknown error, and then the message Bytes written is printed (even though, evidently, nothing is written, but I'm just using it as a status message).
Server.cpp
#include "Server.h"
Server::Server(QObject *parent) : QObject(parent)
{
server = new QTcpServer(this);
qDebug() << connect(server, SIGNAL(newConnection()), SLOT(newConnection()));
qDebug() << connect(server, SIGNAL(bytesWritten()), SLOT(bytesWritten()));
qDebug() << "Listening:" << server->listen(QHostAddress::Any, 1451);
server->waitForNewConnection(-1);
}
void Server::newConnection()
{
qDebug("Connection received");
client = server->nextPendingConnection();
client->write("Some random data\n");
bool returnValue = client->flush();
qDebug() << "Return value: " << returnValue;
qDebug() << client->waitForBytesWritten(-1);
qDebug() << "Error: " << client->errorString();
qDebug() << "Bytes written";
}
void Server::bytesWritten(qint64 bytes)
{
qDebug() << "Bytes written: " << QString::number(bytes);
}
void Server::writeData(std::string data)
{
QByteArray byteArray = QByteArray(data.c_str());
qDebug() << "Write data: " << QString::fromStdString(data);
client->write(byteArray);
}
Client.cpp
#include "Client.h"
#include "mainwindow.h"
Client::Client(QObject* parent) : QObject(parent)
{
socket = new QTcpSocket(this);
(void)QObject::connect(socket, SIGNAL(connected()), this, SLOT(connected()));
qDebug() << "Connect signal" << QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
bool Client::connectToHost(QString host)
{
socket->connectToHost(host, 1451);
socket->waitForConnected();
qDebug() << "Error: " << QString::number(socket->error() == QAbstractSocket::UnknownSocketError);
return true;
}
void Client::connected()
{
qDebug("Socket is connected");
qDebug() << QString::number(socket->state() == QAbstractSocket::ConnectedState);
}
void Client::readData()
{
qDebug("Read data");
QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender());
QByteArray data = sender->readAll();
std::string character = data.toStdString();
qDebug() << "Character received: " << QString::fromStdString(character);
MainWindow::characterReceived(character);
}
Related
A proxy application which the client side redirect all connections to the server side application.
At the server side, QTcpServer::newConnection() signal is emitted and we connect QTcpSocket::readyRead() signal to our slot which receives the data from client and redirect the data to 3rd party application for handling HTTP/HTTPS requests. readyRead() signal emitted when client sends HTTP request but this does not happen with HTTPS requests.
Tried: Set QTcpServer::proxy() and QTcpSocket::proxy() to QNetworkProxy::NoProxy, use QSslSocket instead of QTcpSocket with ignoreSslErrors().
Code:
Client::Client(QObject *parent, QTcpSocket* clientCon)
: QObject(parent)
{
client = clientCon;
tunnel = new QSslSocket();
if (serverApp) // If application running as server
tunnel->connectToHost("127.0.0.1", 808); // Connect to CCProxy which handle the requests for us
else
{
tunnel->setProxy(QNetworkProxy::NoProxy);
tunnel->ignoreSslErrors();
tunnel->connectToHost(QHostAddress("serverip"), 9090); // Connect to the server side if running as client
}
tunnel->waitForConnected(5000); // 5 seconds timeout
if (tunnel->state() == tunnel->ConnectedState)
{
QObject::connect(client, SIGNAL(readyRead()), this, SLOT(ClientDataReceived()));
QObject::connect(tunnel, SIGNAL(readyRead()), this, SLOT(TunnelDataReceived()));
QObject::connect(client, SIGNAL(disconnected()), this, SLOT(ClientDisconnected()));
QObject::connect(tunnel, SIGNAL(disconnected()), this, SLOT(ClientDisconnected()));
}
}
Client::~Client()
{
}
bool Client::IsTunnelEstablished()
{
return tunnel->state() == tunnel->ConnectedState ? true : false;
}
QString Client::GetTunnelErrorString()
{
return tunnel->errorString();
}
void Client::ClientDataReceived()
{
QByteArray data = client->readAll();
qDebug() << "Client [" << client->peerAddress().toString().remove(" ") << ":" << client->peerPort() << "] Data Received: " << data.size();
qint64 wr = tunnel->write(data, data.size());
if (wr != data.size())
qDebug() << "QTcpSocket::write() failed!"; // Never happened
data.clear();
tunnel->flush();
}
void Client::TunnelDataReceived()
{
QByteArray data = tunnel->readAll();
qDebug() << "Client Tunnel [" << client->peerAddress().toString().remove(" ") << ":" << client->peerPort() << "] Data Received: " << data.size();
client->write(data);
data.clear();
client->flush();
}
void Client::ClientDisconnected()
{
/*if (tunnel->state() == tunnel->ConnectedState)
tunnel->close();*/
qDebug() << "[" << client->peerAddress().toString().remove(" ") << ":" << client->peerPort() << "] Disconnected";
QObject::disconnect(client, SIGNAL(readyRead()), this, SLOT(ClientDataReceived()));
QObject::disconnect(tunnel, SIGNAL(readyRead()), this, SLOT(TunnelDataReceived()));
QObject::disconnect(client, SIGNAL(disconnected()), this, SLOT(ClientDisconnected()));
QObject::disconnect(tunnel, SIGNAL(disconnected()), this, SLOT(ClientDisconnected()));
client->deleteLater();
tunnel->deleteLater();
delete this; // Self delete
}
Server Initialization:
void BaseProtocol::StartServer()
{
server = new QTcpServer();
server->setProxy(QNetworkProxy::NoProxy);
server->listen(QHostAddress("0.0.0.0"), serverApp ? 9090 : 5050); // 9090 for server, 5050 for client
qDebug() << QObject::connect(server, SIGNAL(newConnection()), this, SLOT(ClientConnecting()));
}
void BaseProtocol::ClientConnecting()
{
QTcpSocket *client = server->nextPendingConnection(); // Accept the connection
qDebug() << "Client Connected: " << client->peerAddress().toString() << ":" << client->peerPort();
Client* clientHandler = new Client(this, client);
if (!clientHandler->IsTunnelEstablished())
{
qDebug() << "Tunnel Connection Failed: " << clientHandler->GetTunnelErrorString() << "\n";
client->disconnect();
client->deleteLater();
delete clientHandler;
}
}
As you see the client and server application are the same but start with different ports. The reason why I use a client side application instead of connecting to the server as proxy directly is because I want to encrypt the data between client and server later. (same problem also exist when connecting directly to server side)
This is supposed to be a transparent proxy so there is no need for SSL/TLS at all.
"Internet Options" are used to set the proxy server to "127.0.0.1:5050" at the client side.
I want to receive UDP messages using QT. The code I use (see bellow) works well, but the problem is that it only works for one message: after receiving one message, the code still running, but it seems that it doesn't receive anything anymore.
Indeed, after the first message received, the console display qDebug() << "in !";, meaning that it enters into the function, but never received other UDP messages.
I already check, I sure the message is well sent by the UDP server. So the problem must come from here. Any suggestions?
Launching UDP when the class is created:
App::App(QWidget *parent)
: QMainWindow(parent), imageLabel(new QLabel)
, scrollArea(new QScrollArea)
{
.....
StartUDP();
....
}
The UDP initialization:
void App::StartUDP()
{
socket = new QUdpSocket(this);
bool result = socket->bind(QHostAddress::AnyIPv4, 17);
qDebug() << result;
if(result)
{
qDebug() << "PASS";
}
else
{
qDebug() << "FAIL";
}
readyRead();
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()),Qt::QueuedConnection);
}
The function that what for UDP signal:
void App::readyRead()
{
qDebug() << "in !";
QHostAddress sender;
quint16 port;
while (socket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(socket->pendingDatagramSize());
socket->readDatagram(datagram.data(),datagram.size(),&sender,&port);
qDebug() <<"Message From :: " << sender.toString();
qDebug() <<"Port From :: "<< port;
qDebug() <<"Message :: " << datagram;
file_name = datagram;
m_SystemTrayIcon->showMessage(tr("Message"), tr("Nouveau fichier détecté"));
}
}
I would have to send Modbus request for specific data, my problem is that I have to use mobile communication, wifi, connect to a custom electronic card, which is right in Modbus RTU.
My working code connecting to the electronic board:
#include "connessione.h"
#include <QModbusTcpClient>
#include <QVariant>
#include <QModbusDataUnit>
#include <QDebug>
connessione::connessione(QObject *parent) : QObject(parent)
{
qDebug() << "here debug " << "ok";
clientX = new QModbusTcpClient();
clientX->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "192.168.222.1");
clientX->setConnectionParameter(QModbusDevice::NetworkPortParameter, 5555);
if (clientX->connectDevice())
{
qDebug() << "connected: " << clientX->state();
}
else
{
qDebug() << "ERRORE" << clientX->errorString();
}
}
void connessione::clickButton(){
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0, 1); // just read input register 40006
//qDebug() << "readUnit" << readUnit.RegisterType;
qDebug() << "readUnit" << clientX->state();
if (auto *reply = clientX->sendReadRequest(readUnit, 255)) // client id 255
{
if (!reply->isFinished())
{
// connect the finished signal of the request to your read slot
qDebug() << "connected" << reply->errorString();
connect(reply, &QModbusReply::finished, this, &connessione::readReady);
}
else
{
qDebug() << "Errore" << reply->errorString();
delete reply; // broadcast replies return immediately
}
}
else
{
qDebug() << "Errore" << reply->errorString();
// request error
}
}
void connessione::readReady()
{
QModbusReply *reply = qobject_cast<QModbusReply *>(sender());
if (!reply)
return;
if (reply->error() == QModbusDevice::NoError)
{
const QModbusDataUnit unit = reply->result();
int startAddress = unit.startAddress(); // the start address,
int value = unit.value(0); // value of the start address + 0
qDebug() << "NESSUN ERRORE" << reply->errorString();
}
else
{
qDebug() << "Errore readReady" << reply->errorString();
// reply error
}
reply->deleteLater(); // delete the reply
}
log string TCP sent:
D/libmodbusMobile.so( 8042): (null):0 ((null)): qt.modbus: (TCP
client) Sent TCP PDU: 0x0300000001 with tId: 2
this is right: 0x0300000001
But unfortunately, my electronic card, the integrated firmware I can not modify, is right with Modbus RTU, so I should change 0x0300000001 to 0x010300000001C1C2 where C1 and C2 are the checksums.
I believe that QModbusDataUnit generate buffer to send. So how to change it? Exist manual solution where I build the buffer?
how to change it and create custom send buffer like the example?
Thanks
I am writing simple client server program in Qt that server is multi thread.
For one server it work correctly and it can send message from client to server but in multi thread form it doesn't work, it connect to thread and also show the message "client connected" but it can't show message sent from client!
I searched a lot bud I couldn't find what is the problem and any solution for it.. Here is my code:
Could you please help me. Thanks in advance.
myserver.cpp
#include "myserver.h"
#include "mythread.h"
myserver::myserver(QObject * parent): QTcpServer(parent)
{
}
void myserver::startserver()
{
int port = 6666;
if (!this - > listen(QHostAddress::Any, port)) {
qDebug() << "Could not start server ";
} else {
qDebug() << "Listening to port ";
}
}
void myserver::incomingConnection(qintptr socketDescriptor)
{
qDebug() << socketDescriptor << " Connecting...";
mythread * thread = new mythread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread - > start();
}
mythread.cpp
#include "mythread.h"
#include "myserver.h"
mythread::mythread(qintptr ID, QObject *parent) : QThread(parent)
{
this->socketDescriptor = ID;
}
void mythread::run()
{
qDebug() << " Thread started";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor)) {
emit error(socket->error());
return;
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
qDebug() << socketDescriptor << " Client connected";
}
void mythread::readSocket()
{
QByteArray Data = socket->readAll();
qDebug()<< socketDescriptor <<" Data in: " << Data;
socket->write(Data);
}
If you read the documentation for the QThread::run function you will see
Returning from this method will end the execution of the thread.
You need to call the QThread::exec function to enter the thread event loop.
I have a server that can handle multiple threads. The server starts and listens, but it is having trouble echoing when an incoming connection is pending.
I am using telnet to open the socket and send data to the server. However, the server only displays that it's listening, but doesn't echo any of the data I type through telnet or signify that there is an incoming connection. I shut off Windows firewall for private networks and still...nothing.
Also tried seeing if the server error string had anything useful to say, but all it is just an empty string.
This is a complete mystery to me and if anyone had anything constructive to note, it'd be much appreciated. Code for the thread and server is below.
server.cpp
#include "myserver.h"
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::StartServer()
{
if(!this->listen(QHostAddress::Any,1234))
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "Listening...";
}
}
void MyServer::incomingConnection(int socketDescriptor)
{
qDebug() << socketDescriptor << " Connecting...";
MyThread *thread = new MyThread(socketDescriptor,this);
connect(thread, SIGNAL(finished()),thread, SLOT(deleteLater()));
thread->start();
}
thread.cpp
#include "mythread.h"
MyThread::MyThread(int ID, QObject *parent) :
QThread(parent)
{ this->socketDescriptor = ID;
}
void MyThread::run()
{
qDebug() << socket->errorString();
//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();
}
void MyThread::readyRead()
{
QByteArray Data = socket->readAll();
qDebug() << socketDescriptor << " Data in: " << Data;
socket->write(Data);
}
void MyThread::disconnected()
{
qDebug() << socketDescriptor << " Disconnected";
socket->deleteLater();
exit(0);
}
Which version of Qt are you using? In Qt 5, the parameter for the function incomingConnection is of type qintptr and not int. Have a look at the following links:
incomingConnection - Qt 5
Qt 5 - Multithreaded server tutorial