PDA

View Full Version : Server don't receive a new request of client



tchoninho
26th May 2011, 21:24
Hi,

I have a server and a client. The request client a information to the server. The first message received is answered by the server. But the second only is received after to disconnect and to connect again.


It follow the source code.


The client send request


void ClientStub::sendRequest(const Message msg)
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_6);

out << (quint16)0;
out << msg;

out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));

tcpSocket->write(block);
tcpSocket->flush();
sended++;
}



The server receive and create a ClientSocket object to treat the connection


void Server::incomingConnection(int socketId)
{
ClientSocket *socket = new ClientSocket();
socket->setSocketDescriptor(socketId);
}



ClientSockt code, it is exchange data with the client


static int countClientSocket = 0;

ClientSocket::ClientSocket(QObject *parent)
: QTcpSocket(parent)
{
connect(this, SIGNAL(readyRead()), this, SLOT(receive()));
// connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));

countClientSocket++;

//#ifdef DEBUG_MACHINE
printf("ctor countClientSocket: %i \n", countClientSocket);
std::cout.flush();
//#endif

nextBlockSize = 0;

}

ClientSocket::~ClientSocket()
{
// abort();
countClientSocket--;

#ifdef DEBUG_MACHINE
printf("dtor countClientSocket: %i \n", countClientSocket);
std::cout.flush();
#endif

}

bool ClientSocket::setSocketDescriptor(int socketDescriptor)
{
QTcpSocket::setSocketDescriptor(socketDescriptor);
return waitForReadyRead(5);
}

void ClientSocket::receive()
{
QDataStream in(this);
in.setVersion(QDataStream::Qt_4_6);

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

in >> nextBlockSize;
}

if (bytesAvailable() < nextBlockSize)
return;

Message msg;
in >> msg;

invoke(msg);
}

void ClientSocket::invoke(Message &msg)
{
QList<QVariant> msgContents = msg.getContents();
WordCounter task = msgContents.first().value<WordCounter>();

msg.setTypes(Message::Info);
msg.setContents(QList<QVariant>() << QString("received request"));

response(msg);
printf("%i - received request\n", msg.getId());

QByteArray normalizedSignature = QMetaObject::normalizedSignature("execute (QList<QVariant> &)");

QVariant retVal;
const QMetaObject *metaObject = 0;
metaObject = task.metaObject();
int methodIndex = -1;
methodIndex = metaObject->indexOfMethod(normalizedSignature);
QMetaMethod method = metaObject->method(methodIndex);

printf("Processing request of: %i \n", task.getKey());

QElapsedTimer timer;
timer.start();
method.invoke(
&task,
Qt::DirectConnection, // Qt::AutoConnection,
Q_RETURN_ARG(QVariant, retVal),
Q_ARG(QList<QVariant>, msgContents)
);
int t = timer.elapsed();

msg.setTypes(Message::Result);
msg.setContents(QList<QVariant>() << retVal
<< QString("Time elapsed: %1 miliseconds").arg(t)); // << "done!");
printf("id: %i, Result: %i \n--------&gt;>> Time elapsed: %i miliseconds\n", task.getKey(), retVal.toInt(), t);

response(msg);

// waitForDisconnected();
// close();
}

void ClientSocket::response(Message msg)
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_6);

out << quint16(0);
out << msg;

out.device()->seek(0);
out << quint16(block.size() - sizeof(quint16));

write(block);
flush();
}




Thanks!!

joyer83
26th May 2011, 22:37
Do you wait in the client side for response before sending next request?

If you don't and just send requests as fast as you can, then in the server side the readyRead() signal might be emitted when there already is couple of requests worth of data waiting in the socket. The receive() slot handles only one request and doesn't check if there is more data available after invoking.

tchoninho
26th May 2011, 23:32
Do you wait in the client side for response before sending next request?

Yes, I do. I put a 'while' for wait the result arrive. The client only continue after.

wysota
27th May 2011, 07:45
What kind of "while" did you put there?

yeye_olive
27th May 2011, 08:50
If I am not mistaken, in the client code you use the condition nextBlockSize == 0 to determine in which of two states the reading operation is. However it seems that you never reset nextBlockSize to 0 after having read a message, therefore the size is only read for the first message. And, as joyer83 pointed out, you do not try to read more than one message.

I would recommend using a separate boolean variable (or, better, a more descriptive enum) to keep track of the current state.

Also, is there a firm guarantee that writing a quint16 to a QDataStream exactly fills the first sizeof(quint16) bytes (with no header beforehand)?