PDA

View Full Version : network client socket without using signals and slots



erqsor
17th March 2011, 04:42
Hello,

I need to use a QTcpSocket for a 3D application (client side). My app has his own event loop, and I can't use signals and slots as the normal way (An QCoreApplication is not created). So I am trying to find an alternativ way.

I made a test application, and remarked that functions waitForXxx of the socket classes can't being used in my case, because I've to block my 3D application for waiting for events, and I can't permit that in my render loop :/

So I'm trying to understand how the eventsLoops of Qt are capturing signals for doing a similar thing in my event loop but it's pretty complicated ^^ (function QEventLoop::processEvents)

What I want exactly :
Adding a refresh function for verifying connection, disconnection, readyRead or readyWrite states of the socket.
State function returns a resfreshed state of the socket.

Someone can give me somes ideas for realising that ?
thanks.

here the code of my test application (we have to type "enter" to connect or disconnect):

#include <QtCore>
#include <QtNetwork>
#include <windows.h>
#include <iostream>

void connectOrDisconnect(QTcpSocket * socket)
{
if ( socket != NULL )
{
if ( socket->state() == QAbstractSocket::UnconnectedState )
{
socket->connectToHost("localhost", 1337);
}
else if ( socket->state() == QAbstractSocket::ConnectedState )
{
socket->disconnectFromHost();
}
else
{
socket->abort();
}
}
}

int main(int argc, char *argv[])
{
QTcpSocket * socket = new QTcpSocket;
int stateEnter;

while (1)
{
int lastStateEnter = stateEnter;
stateEnter = GetKeyState(VK_RETURN);
if ( lastStateEnter != stateEnter && GetKeyState(VK_RETURN) < 0 )
{
connectOrDisconnect( socket );
}

if ( socket->state() == QAbstractSocket::UnconnectedState && socket->waitForConnected(100) )
std::cout << "disconnected" << std::endl;
if ( socket->state() == QAbstractSocket::ConnectedState && socket->waitForDisconnected(100) )
std::cout << "disconnected" << std::endl;
if ( socket->waitForReadyRead(100) )
std::cout << "ReadyRead" << std::endl;
if ( socket->bytesAvailable() )
std::cout << QString::number(socket->bytesAvailable()).toStdString() << " bytes available" << std::endl;

switch ( socket->state() )
{
case QAbstractSocket::UnconnectedState:
std::cout << "UnconnectedState" << std::endl;
break;
case QAbstractSocket::HostLookupState:
std::cout << "HostLookupState" << std::endl;
break;
case QAbstractSocket::ConnectingState:
std::cout << "ConnectingState" << std::endl;
break;
case QAbstractSocket::ConnectedState:
std::cout << "ConnectedState" << std::endl;
break;
case QAbstractSocket::BoundState:
std::cout << "BoundState" << std::endl;
break;
case QAbstractSocket::ClosingState:
std::cout << "ClosingState" << std::endl;
break;
case QAbstractSocket::ListeningState:
std::cout << "ListeningState" << std::endl;
break;
default:
std::cout << "Unknow" << std::endl;
break;
}
}
}

If found this code in QAbstractSocket::waitForConnected :

if (d->socketEngine && d->socketEngine->waitForWrite(timeout, &timedOut) && !timedOut) {
d->_q_testConnection();
} else {
d->_q_connectToNextAddress();
}
but I don't know what is d ? and socketEngine (maybe the platforme dependant socket object) ?

unit
17th March 2011, 15:37
but I don't know what is d ? and socketEngine (maybe the platforme dependant socket object) ?

see src:
d created by macros Q_D(QAbstractSocket);

from qglobal:



#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()

squidge
17th March 2011, 18:04
Throw your network stuff into another thread and use the WatFor* methods is probably the easiest way if you don't want (or can't) use signals and slots.

erqsor
17th March 2011, 18:13
OK, thanks

That's a good Idea squidge, but can I create and start a QThread if I don't have a QApplication in my process ?

squidge
17th March 2011, 19:58
I've no idea, try it and see :) I'd imagine only the signal stuff wouldn't work, so you'd probably have to override the run method so it doesn't start an event loop?

If QThread doesn't work there are many other ways of creating a new thread.

erqsor
17th March 2011, 20:07
Hum, OK thanks I will try :)

erqsor
24th March 2011, 05:55
Done. It's working fine, with some mutex, but I'm afraid that the 3D application will be slowed by a heavy network communication :/ (cause of the locks of the 3D application thread when accessing to the socket).
But I will test that when my project will be more advanced :)

wysota
24th March 2011, 09:28
I would suggest to try and rethink your design and integrate everything with QCoreApplication. Qt event loop is constructed in such a way that it allows easy integration with other event loops. You can even substitute the regular event loop with your own by implementing the QAbstractEventDispatcher interface.