2
votes

BSD stream sockets are full duplex, meaning two connected parties can both send/receive at the same time.

A QTcpSocket (qt socket implementation) has asynchronous support, non blocking mode, but can only belong to one thread, see qt docs.

Event driven objects may only be used in a single thread. Specifically, this applies to the timer mechanism and the network module.

Let's say I want a transmit/tx thread and a separate receive/rx thread to use the same socket and send/receive data at the same time.

In my understanding this can be 'done' via qt signals/slots, but the socket thread will never really perform the send() and the receive() simultaneously. It just runs the event loop which will do this in a serial fashion and emit the signals when send/receive is done.

Yes, my rx and tx threads can work concurrently and handle the notifications via qt slots, but the socket itself is never really used in full duplex mode.

Is it correct to say that: considering one endpoint only, in the socket thread, its send() and receive() calls are always serial, never simultaneous? (because the event loop thread is one thread only)

1
"Let's say I want a tx thread and a separate rx thread to use the same socket and send/receive data at the same time." Nope, can't do it.All operations on a given socket MUST be performed in the same thread. If you try what you proposed it will fail several Qt debug assertions. In addition, to put a socket in a different thread from the QTcpServer you'll need to subclass it and do a little trickery.Nicolas Holthaus
in my example there are three threads: socket thread, rx thread and tx thread. Socket thread runs the event loop and is the only one performing actual send()/receive(). Rx and Tx threads are just manipulating the socket via signals/slots or events. This is 100% possible. My question is about what really happens in the socket thread, where the event loop is really serializing the socket calls.chris

1 Answers

5
votes

In my understanding this can be 'done' via qt signals/slots, but the socket thread will never really perform the send() and the receive() simultaneously. It just runs the event loop which will do this in a serial fashion and emit the signals when send/receive is done.

True, but keep in mind that the kernel buffers incoming and outgoing data, and QTCPSocket sets the socket to non-blocking, so that the send() and recv() calls always return immediately and never block the event-loop. That means that the actual processes of sending and receiving data will happen simultaneously (inside the kernel), even if the (more-or-less instantaneous) send() and recv() calls technically do not. (*)

Yes, my rx and tx threads can work concurrently and handle the notifications via qt slots, but the socket itself is never really used in full duplex mode. Is this correct?

That is not correct -- the socket's data streams can (and do) flow both ways across the network simultaneously, so the socket really is full-duplex. The full-duplex capability is present whether you are using a single thread or multiple threads.

(*) You can test this with a single-threaded Qt program that uses a QTCPSocket to send or receive data, by simply disconnecting your computer's Ethernet cable during a large data transfer. If the QTCPSocket's send() or recv() calls are blocking until completion, that would block the GUI thread and cause your GUI to become unresponsive until you reconnect the cable (or until the TCP connection times out after several minutes).