PDA

View Full Version : TCP server-client app problem



pogostick
24th January 2010, 14:38
Any idea what's wrong with my TCP server-client app? I've been copying the TCP Trip Planner example in the book (so no threads used). The difference is that I've changed it so that it doesn't close the connection after one exchange of data between client/server. It works at first; client sends a request and gets a response, but after that the response is always empty (integers come in as 0 and strings as ""). I've got a feeling there's a simple solution and I'm just doing this wrong.

Here's the code. Well, the relevant part (I hope). Every signal and slot is connected appropriately.

Client:

QTcpSocket tcpSocket;
quint16 nextBlockSize;
quint8 mode;
//constructor
connect(&tcpSocket, SIGNAL(readyRead()), this, SLOT(readServer()));
//connectToServer()
tcpSocket.connectToHost("127.0.0.1", 40567);
nextBlockSize = 0;

mode = 4;
//sendRequest()
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_4);
out << quint16(0) << quint8('S') << mode;
out.device()->seek(0);
out << quint16(block.size() - sizeof(quint16));
tcpSocket.write(block);
//readServer()
DataStream in(&tcpSocket);
in.setVersion(QDataStream::Qt_4_4);

for(;;)
{
if(nextBlockSize == 0)
{
if(tcpSocket.bytesAvailable() < sizeof(quint16))
break;
in >> nextBlockSize;
}

if(nextBlockSize == 0xFFFF)
{
//closeConnection();
break;
}

if(tcpSocket.bytesAvailable() < nextBlockSize)
break;

quint8 modev;

in >> modev;

switch(modev)
{
case 4:
//stuff
break;
}

nextBlockSize = 0;
}
Server side (after creating a new object to handle the connection with the client):

//reading and writing
QDataStream in(this);
in.setVersion(QDataStream::Qt_4_4);

if(nextBlockSize == 0)
{
if(bytesAvailable() < sizeof(quint16))
return;
in >> nextBlockSize;
}

if(bytesAvailable() < nextBlockSize)
return;

quint8 requestType;
quint8 mode;

in >> requestType;
if(requestType == 'S')
{
in >> mode;

if(mode == 4)
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_4);
out << quint16(0) << mode;
out.device()->seek(0);
out << quint16(block.size() - sizeof(quint16));

write(block);
}
}

nextBlockSize = 0;

wysota
24th January 2010, 17:51
Qt uses sockets in asynchronous manner, it doesn't block on read or write calls thus you can't write to the socket and immediately start reading from it expecting a response to be already there.

pogostick
24th January 2010, 18:15
I'm sorry, I didn't make it very clear. Those three pieces of code (starting with the comment lines) are actually separate functions. First the connection is established, then a request is sent when the user e.g. presses a button, and finally when the readyRead() signal is emitted the client reads the data. There's just so much stuff in between I thought it'd look more clear.

wysota
24th January 2010, 18:16
So which part is where?

pogostick
24th January 2010, 18:39
Okay, I edited the first post.

wysota
24th January 2010, 23:42
It's hard to find the error in such code if you don't see the context. I suggest you inject calls to QDataStream::status() to see which part of the spaghetti... eeem... I mean... code gets executed and what breaks the stream.

boudie
25th January 2010, 08:13
@pogostick:
Please show us the complete source of the client and the server. You are not showing complete methods, so there is no way that we ever know what you are doing outside what you're showing us.
Maybe the problem is beacuse of variables going out of scope. But this way will we never know.

That said, please check if you're not close()ing the connection in the server after sending a block of data, as the code in your book does, C++ GUI programming with Qt4 (ISBN 0-13-187249-4).