Simplest QT TCP Server - c++

What would I need to receive data from a client?
QTcpServer Server;
if(!Server.listen("127.0.0.1", 9000)) {
return;
}
connect(Server, SIGNAL(newConnection()), this, SLOT(ReceiveData()));
Is this correct so far? What do I need in ReceiveData? Do I really need another function to receive the data? I would like to save it in a QByteArray
Thanks

As this hasn't been answered, here's a really basic example.
In your ReceiveData slot, you would need to accept the connection from the server.
In Qt's QTcpServer this is done by calling nextPendingConnection().
So the QTcpServer's newConnection slot will call your ReceiveData slot.
In your receivedata slot, you can do something like:
void ReceiveData()
{
QTcpSocket *socket = server->nextPendingConnection();
if (!socket)
return;
qDebug("Client connected");
socket->waitForReadyRead(5000);
QByteArray data = socket->readAll();
qDebug(data.constData());
socket->close();
}
Note: This is a blocking example, the waitForReadyRead will hang the thread for up to 5000 milliseconds.
To do a non blocking example, you need to connect another slot to the new socket's readyread signal.

Have you seen this example:
http://doc.qt.io/qt-5/qtnetwork-fortuneserver-server-cpp.html
PS:
Yes, you need at least one callback function to:
1) accept new connections
2) Receive and Send data on the connect(s)

Related

Detecting ip camera connection using QNetworkAccessManager?

I'm using two ip cameras from Axis Communications for my application. I want to check if the cameras are ever disconnected. Is it possible to do so by the use of QNetworkAccessManager and QNetworkReply?
The prototype of what I tried is like the following way:
QNetworkAccessManager *m_networkAccessManager = new QNetworkAccessManager();
QNetworkReply *m_networkReply = m_networkAccessManager->get(QNetworkRequest(camUrl));
if (!m_networkReply)
{
delete m_networkAccessManager;
qDebug()<<"Camera not found"<<endl;
}
connect(m_networkReplyCam, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(cameraDisconnected(QNetworkReply::NetworkError)));
void MainWindow::cameraDisconnected(QNetworkReply::NetworkError)
{
qDebug()<<"Camera Disconected"<<endl;
}
But the slot cameraDisconnected never seem to gets invoked. I also tried connect with finished() signal from QNetworkReply like the following:
connect(m_networkReplyCam, SIGNAL(finished()), this, SLOT(cameraDisconnected()));
But even then the slot never gets called.
What am I doing wrong?
Thanks.
Your request will timeout after some time if the host is unreachable. There is no built-in way to set specific timeout in QNetworkRequestor QNetworkAccessManager so one possibility is to implement your own timer to abort after a particular time. There are multiple examples to do that like 1, 2 and 3.

QT even processing while waitForConnected is running

I have loop that is supposed to try to connect to each IP from range:
for(...){
socket->connectToHost(addres,port);
do stuff....
if(socket->waitForConnected(2000))
{
do stuff...
if(socket->waitForReadyRead(1000))
{
do stuff...
}
else do stuff...
}
do stuff ......
}
During connection atempts UI freezes, because there is no event processing in the meantime. I tried to add QCoreApplication::processEvents(); inside the loop, however it still freezes for long time during waitForConnected, and I also tried to use timers, but this also wont work as QT needs event processing to use timers in the first place. Is there any way to provide event processing (prevent UI from freezing) during conection, or using some non-blocking alternative for waitForConnection?
The best approach is to use QTcpSocket in an asynchronous mode by connecting the signals of the socket to relevant slots :
connect( socket, SIGNAL(connected()), this, SLOT(onConnected()) );
connect( socket, SIGNAL(readyRead()), this, SLOT(tcpReady()) );
connect( socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(tcpError(QAbstractSocket::SocketError)) );
And handle your application logic in the slots :
void MyClass::onConnected()
{
...
}
void MyClass::tcpError(QAbstractSocket::SocketError error)
{
...
}
You can also use a local event loop using QEventLoop and connect the signals connected, error, ... of your QTcpSocket to the quit slot of QEventLoop. This way when the socket is connected or an error is occured, the local event loop quits and the rest gets executed :
socket->connectToHost(addres,port);
QEventLoop loop;
loop.connect(socket, SIGNAL(connected()), SLOT(quit()));
loop.connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(quit()));
loop.exec();
//...
I should not that it's the standard pattern for "blocking wait without blocking the UI".
Please write out 100 times 'I must not wait in GUI event-handlers'.
Use async signals or thread off the comms.

Qt incomingConnections not called

I have compiled Qt's Trip Planner example that uses QTcpSocket and QTcpServer to create a client and server.
The problem is, the server's incomingConnection() slot is not being called. Even though the client connects to the server successfully. Therefore, the socket's readyRead() signal is never emitted and the client gets no data back.
tripserver.cpp
TripServer::TripServer(QObject *parent)
: QTcpServer(parent)
{
}
void TripServer::incomingConnection(int socketId)
{
qDebug() << "Incoming Connection";
ClientSocket *socket = new ClientSocket(this);
socket->setSocketDescriptor(socketId);
}
If I add a newConnection() slot, it gets called. So what is going on?
Found my answer.
The parameter list has changed since Qt 4.8.1
http://qt-project.org/doc/qt-5.0/qtnetwork/qtcpserver.html#incomingConnection
void TripServer::incomingConnection(qintptr socketId){}

Problems with reading data from QTcpSocket

I've modified the threaded fortune-server from Qt examples.
The client connects to the server and then sends a header to authenticate.
tcpSocket = new QTcpSocket();
tcpSocket->connectToHost(addr, port);
QByteArray block = "someheader";
int x = tcpSocket->write(block);
qDebug() << x;
The client seems OK here and qDebug prints the actual size of block.
On the server side I've predefined incomingConnection and I start thread to each new connection.
void Server::incomingConnection(int socketDescriptor) {
const QString &str = vec[qrand() % vec.size()];
SpellThread *thread = new SpellThread(socketDescriptor, str);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
qDebug() << " -- incoming connection";
thread->start();
}
I'm connecting sock to check is there something to read. (sock here is QTcpServer*)
void SpellThread::run() {
qDebug() << " -- in spellthread";
connect(sock, SIGNAL(readyRead()), this, SLOT(checkBytes()));
//....
qDebug() << " -- end spellthread";
}
The first problem is that when I'm sending data from the client, readyRead is not fired. (I've added debug message in checkBytes)
Messages are:
-- incoming connection
-- in spellthread
-- end spellthread
Although the client prints the actual size of header length.
The second problem is that checkBytes currently is very bad-designed. First it checks is header OK and sets a flag, then it gets the size of message and sets another flag and finally it gets the real message. This is very clumsy. I first tried to escape signals and instead use sock->waitForReadyRead(). However it always returns false. (From the docs: "Reimplement this function to provide a blocking API for a custom device. The default implementation does nothing, and returns false.").
So how to really make a client/server application in Qt with multiple clients and multiple reads/writes? I really want suggestions to improve design of my application and to solve my current two problems.
You can't use slots or socket signals with a thread without calling QThread::exec() to start an event loop within that thread/the run function.
Since your checkBytes slot belongs to QThread, it wouldn't be executed by the thread (there is a detailed article about QThreads here)
The closest example that seems to already do what you want is the Network Chat (particularly the two classes Server and Connection).
----------Edit
If you need to use threads (without any slot), the QTcpSocket object must belongs to the same thread as the one where you call waitForReadyRead. For example, with:
SpellThread::SpellThread(int socketDescriptor, const QString & str) {
tcpSocket = new QTcpSocket(); // There should be no parent to be able
// to move it to the thread
tcpSocket->moveToThread(this);
...
Or by creating the QTcpSocket object inside the run function so that it automatically belongs to that thread (it was briefly explained in the fortune example).
If you allocate the QTcpSocket dynamically, and because it won't have a parent, you should also delete it manually.

QTcpServer: Send HTTP/1.0 200 OK to connected client

I set up a QTcpServer to listen to a Shoutcast stream. The newConnection()-signal gets fired as it should:
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(handleClientComm()));
void IcecastServer::handleClientComm(){
QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
qDebug() << clientConnection->write("HTTP/1.0 200 OK\r\n\r\n" ) << endl;
clientConnection->flush();
}
How do I send HTTP 200 ?
You must extract QTcpSocket object from QTcpServer with nextPendingConnection() call when the newConnection() signal was emitted. And then you must call writeData() on the extracted QTcpSocket object.
The key here is that Listening socket (QTcpServer) is only responsible for creating Connection Sockets (or QTcpSocket) each time a new client connects. And the QTcpSocket is responsible for the actual communication with a specific client.
Maybe you can be more specific what exactly does not work for you and what have you tried? It would also be nice if you could provide us with wireshark PCAP if something does not seem to work as expected?