Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-interest Archive, March 2008
QTcpServer: incomingConnection() but no readyRead()


Message 1 in thread

Linux, Qt 4.3.2.

1. I have a non-threaded QTcpServer subclass called IPCListener
with an incomingConnection() slot like so:

> void IPCListener::incomingConnection(int socketd)
> {   
>     mdp_log(QObject::tr("received incoming connection"));
> 
>     IPCReader* reader = new IPCReader(recipient_, this);
>     reader->setSocketDescriptor(socketd);
> }

The IPCReader class is a subclass of QTcpSocket like this:

> IPCReader::IPCReader(Runnable* dest,
>                      QObject*  parent)
>             : QTcpSocket(parent),
>               destination_(dest),
>               message_length_(0)
> {   
>     connect(this, SIGNAL( readyRead() ),    this, SLOT( read_client() ));
>     connect(this, SIGNAL( disconnected() ), this, SLOT( deleteLater() ));
> }
>
> void IPCReader::read_client()
> {
>     mdp_log(QObject::tr("reading from client"));
> 
> ...
> }

2. When I run this code from the main thread, and send data to
it from a corresponding client, I see the following:

a) the IPCListener listens on an appropriate port correctly.

b) the client connects to the IPCListener and delivers the
correct amount of data (as reported by the return value of
QTcpSocket::write(QByteArray)) and then closes its side of
the connection.

c) the incomingConnection() slot runs and constructs an IPCReader

d) the read_client() slot never runs, as if readReady() is never
delivered.

e) the IPCReader dtor runs.

Can any one see what's going wrong or suggest a way to track
it down ?

-- 
 [ signature omitted ] 

Message 2 in thread

On Tuesday 04 March 2008 09:27:58 Stephen Collyer wrote:
> 2. When I run this code from the main thread, and send data to
> it from a corresponding client, I see the following:
>
> a) the IPCListener listens on an appropriate port correctly.
>
> b) the client connects to the IPCListener and delivers the
> correct amount of data (as reported by the return value of
> QTcpSocket::write(QByteArray)) and then closes its side of
> the connection.
>
> c) the incomingConnection() slot runs and constructs an IPCReader
>
> d) the read_client() slot never runs, as if readReady() is never
> delivered.
>
> e) the IPCReader dtor runs.
>
> Can any one see what's going wrong or suggest a way to track
> it down ?

Are you sure the client did send any data? Note that QTcpSocket::write does 
not actually write, it simply queues the data for writing. If you call 
abort() or destroy the socket immediately after that, the data is lost and 
not sent.

You must call close() or disconnectFromHost() and then wait for the data to 
really go away. I'd do something like this on the client side:

  QTcpSocket *socket = new QTcpSocket;
  connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
  socket->connectToHost(remoteHost, remotePort);
  socket->write(data);
  socket->disconnectFromHost();
  socket = 0;  // forget about it

Also note that I fixed a bug in that case above (connect, write, disconnect 
without any waitFor) for 4.4.0. Qt 4.3.4 is still affected by that bug, so 
you'll need at least one waiting (waitForConnected, waitForBytesWritten or 
write at least one slot connected to the corresponding signals).

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 3 in thread

Thiago Macieira wrote:

> Are you sure the client did send any data? Note that QTcpSocket::write does 
> not actually write, it simply queues the data for writing. If you call 
> abort() or destroy the socket immediately after that, the data is lost and 
> not sent.

Thiago, thanks for the rapid response. I didn't realise that the
socket had to be flushed explicitly before destruction. This fixes
the problem. The code now looks like the following and works fine:

> qint64 bytes_written = tcpsocket_.write(data);                              
> if (bytes_written != data.size())                                           
> {   
>  ...
> }                                                                           
>     
> tcpsocket_.disconnectFromHost();                                            
>     
> if (! tcpsocket_.waitForBytesWritten(-1))                                   
> {
>  ...
> }
>
> return;                                                                           

However, it makes me wonder what happens if I'm trying to
send a huge amount of data: surely it can't all be buffered
until I call disconnectFromHost() ? Why doesn't it deliver the
data directly to the underlying socket ?

-- 
 [ signature omitted ] 

Message 4 in thread

On Tuesday 04 March 2008 10:57:10 Stephen Collyer wrote:
> However, it makes me wonder what happens if I'm trying to
> send a huge amount of data: surely it can't all be buffered
> until I call disconnectFromHost() ? Why doesn't it deliver the
> data directly to the underlying socket ?

It is buffered. You should write in chunks instead and use 
waitForBytesWritten. What I usually do is that I write chunks as fast as 
possible to keep the buffer full, but not too full. That is, if 
bytesToWrite() > 128k, stop writing and just wait. Otherwise, write one more 
chunk.

When you're done writing, disconnectFromHost() and waitForDisconnected().

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.