Since some time I have been working with Qt (sorry for my english). I'm now working with QtNetwork.
I need to create a client-server like system. The basic ideas are these:
The IP's of both (clients and server) can change. There is no way to store the server IP on a configuration file on the client. So, the server must make public it's IP in some way and the clients must be able to detect the server IP to connect.
The clients must be able to work without the server, and update the server (once connected) of it's work.
The clients and the server are running in the same WLAN network, so, there is no need to connect over internet.
This new system is intented to replace and old system (also, clients and a server). The old server communicates to the clients only using UDP broadcast messages, so, somethimes the messages get lost.
So, for the first point, I have implemented in the server a timer. This timer, every X time, sends a broadcast message over UDP with a message "Connect to Server". The idea of this message is that the clients detect such message and get the server IP to connect.
The server uses a QTcpServer to detect clients connections, and per client, stores a new QTcpSocket to communicate.
The clients uses a TcpSocket to connect once they get the server IP.
Sounds simple.
I have implemented the connection system, and, in a local machine (the server and some clients running on the same machine) the system works without problems. The connections can be done and the communication works. Both client and server has been compiled on Chakra Linux 64 bit using gcc 4.7.2. The Qt version installed on the system is 4.8.4.
Now, I have tested the system with two real machines (the server running on Chakra Linux 64 bits and the clients running on Windows 7 (some 32 bits and another 64 bits) and two Windows 8 (only 32 bits)). The Windows version of the clients has been compiled on a Virtual Machine (VirtualBox 4.2.4) running Windows 7 32 bit with Qt 4.8.3 and MingW 4.6.2. The Windows clients runs all a 32 bit compiled version of the client (all the 32 bit Windows machines and the 64 bit Windows machine).
The clients can detect and read the broadcast messages (UDP, working on port 45454), once they get the server IP (the IP detected is correct), they try to connect.
The problem is that, from 7 clients, only one Windows 8 have connected once. All the clients try to connect, and all of it's QTcpSocket emits the "connected" signal, but the server doesn't detect any connection.
This is totally random, since sometimes I can connect 1 or 2 clients. Other times none.
This code is for the client broadcast initialization.
broadcast_socket = new QUdpSocket ();
server_connection = new QTcpSocket ();
if ( broadcast_socket->bind ( QHostAddress::Any , cfg->networkControl ()->udpPort () ) == false )
{
cout << ">> NetworkManager: Error setting port " << cfg->networkControl ()->udpPort () << " for UDP broadcast listen." << endl;
}
connect ( broadcast_socket , SIGNAL ( readyRead () ) , this , SLOT ( broadcastMessageReceived () ) );
connect ( server_connection , SIGNAL ( readyRead () ) , this , SLOT ( serverMessageReceived () ) );
connect ( server_connection , SIGNAL ( disconnected () ) , this , SLOT ( serverConnectionLost () ) );
connect ( server_connection , SIGNAL ( connected () ) , this , SLOT ( serverConnected () ) );
This code is from the client, when receiving a server broadcast message.
void NetworkManager::broadcastMessageReceived ( void )
{
while ( broadcast_socket->hasPendingDatagrams () )
{
QByteArray datagram;
QHostAddress sender_adress;
datagram.resize ( broadcast_socket->pendingDatagramSize () );
broadcast_socket->readDatagram ( datagram.data () , datagram.size () , &sender_adress );
server_ip = sender_adress;
QString message ( datagram.data () );
cout << ">> NetworkManager: Broadcast message received: " << message.toStdString () << endl;
if ( message == QString ( "0:%1" ).arg ( NetworkMessages::ConnectToServer ) )
{
if ( connection_status == 0 ) // If 0, there is no connection still.
{
cout << endl << " Server asking for connection." << endl;
cout << " Server IP: " << sender_adress.toString ().toStdString () << endl;
cout << " Trying to connect." << endl;
server_connection->connectToHost ( sender_adress , cfg->networkControl ()->tcpPort () );
cout << " Waiting for responce." << endl;
connection_status = 1;
break;
}
}
}
return;
}
On the server side, I have this code to initialize:
connection_server = new QTcpServer ();
connect ( connection_server , SIGNAL ( newConnection () ) , this , SLOT ( connectClient () ) );
if ( connection_server->listen ( QHostAddress::Any , cfg->networkControl ()->tcpPort () ) == false )
{
cout << ">> NetworkManager: Error setting port " << cfg->networkControl ()->tcpPort () << " for TCP server use" << endl;
}
And this is part of the code to connect a new client:
void NetworkManager::connectClient ( void )
{
cout << ">> NetworkManager: New client request." << endl;
QTcpSocket* new_client = connection_server->nextPendingConnection ();
connection_sockets[ i ] = new_client; // This is a QList of QTcpSocket pointers, the value of 'i' is calculated previously
connect ( new_client , SIGNAL ( readyRead () ) , connection_listeners[ i ] , SLOT ( readyRead () ) );
connect ( new_client , SIGNAL ( disconnected () ) , connection_listeners[ i ] , SLOT ( disconnected () ) );
connection_state[ i ] = 1;
cout << " Asking to client with IP " << new_client->peerAddress ().toString ().toStdString () << " identify." << endl;
connection_state[ i ] = 1;
sendToClient ( QObject::tr ( "0:%1" ).arg ( NetworkMessages::IdentifyYourself ) , i );
}
The "sendToClient" member function only sends a message to the client once connected.
So, the problem is that, I don't know why there is so random connections, most of the time being false connections (the client, again, emits the connected signal, but in the server side there is none signal emited when a client connects...).
I don't know what I'm doing wrong...
Both clients and server works with UDP port 45454 and TCP port 8888. I already changed the TCP port values (on client, server and both) and the same story. I have changed the TCP por and if there is not the same port on both, the messages doesn't reach the clients...
Sorry for the long text, but I think is best to tell you what I have done...
I'm looking for advice of wich one can be my problem, or if my code have some problem... but remember, sometimes (and just sometimes) one or two clients can really connect...