views:

363

answers:

0

I'm developing an application that uses IPC between a local server and a client application. There is nothing particular to it, as it's structured like the Qt documentation and examples.

The problem is that the client sends packets frequently and connecting/disconnecting from the server local socket (named pipe on NT) is very slow. So what I'm trying to achieve is a "persistent" connection between the two applications.

The client application connects to the local server (QLocalServer) without any problem:

void IRtsClientImpl::ConnectToServer(const QString& name)
{   
    connect(_socket, SIGNAL(connected()), this,  SIGNAL(connected()));
    _blockSize = 0;
    _socket->abort();
    _socket->connectToServer(name, QIODevice::ReadWrite);
}

And sends requests also in the traditional Qt manner:

void IRtsClientImpl::SendRequest( quint8 cmd, const QVariant* const param_array, 
            unsigned int cParams )
{
    // Send data through socket

    QByteArray hdr(PROTO_BLK_HEADER_PROJ);
    QByteArray dataBlock;
    QDataStream out(&dataBlock, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);

    quint8 command = cmd;

    out << blocksize_t(0) // block size
     << hdr  // header
     << quint32(PROTO_VERSION_PROJ) // protocol version
     << command        // command
     << cParams;     // number of valid parameters

    for (unsigned int i = 0; i < cParams; ++i)
     out << param_array[i];

    // Write the current block size
    out.device()->seek(0);
    out << dataBlock.size() - sizeof(blocksize_t);
    _socket->write(dataBlock);
}

No problem. But the trick resides on the readyRead() signal in the server-side. Here's the current implementation of the readyRead() handling slot:

void IRtsServerImpl::onReadyRead()
{
    QDataStream in(_lsock);
    in.setVersion(QDataStream::Qt_4_5);

    if (_blocksize == 0)
    {
     qDebug("Bytes Available on socket: %d", _lsock->bytesAvailable());
     if (_lsock->bytesAvailable() < sizeof(blocksize_t))
      return;

     in >> _blocksize;
    }

    // We need more data?
    if (_lsock->bytesAvailable() < _blocksize)
     return;

    ReadRequest(in);

    // Reset
    _blocksize = 0; 

}

Without setting _blocksize to zero I could not receive more data, only the first block group (I would expect an entire block to arrive without segmentation since this is through a pipe, but it does not, go figure). I expect that behavior, sure, since the _blocksize does not represent the current stream flow anymore. All right, resetting _blocksize does the trick, but I can't resend another packet from the client without getting an increasing array of bytes on the socket. What I want is to process the request in ReadRequest and receive the next data blocks without resorting to connecting/reconnecting the applications involved.

Maybe I should 'regulate' the rate of the incoming data?

Thank you very much.