QTcpSocket concatenation of incoming frame
-
Hi,
I'm working with QTcpSocket but I have a concantenation problem on incoming frame.
My distant system is sending me 2 frames of 16 bytes (I can see them both on wireshark), but when I receive them on my onReadyRead function, socket->bytesAvailable() is returning 32, because the 2 frames have been received in the buffer and concatened).
Is there a way to retrieve them as 2 frames, as they have been really emitted on the ethernet?
(because on the rest of my code, I don't always know the size of the frames, it is not always 16 bytes).Thanks in advance,
Best regards
Vincent
-
@modelvincent said in QTcpSocket concatenation of incoming frame:
Is there a way to retrieve them as 2 frames, as they have been really emitted on the ethernet?
Why? You should never depend on such details, instead implement a protocoll. TCP is a stream, it is up to TCP/IP stack to split sent data in packets and accumulate them again on receiver side.
-
@modelvincent said in QTcpSocket concatenation of incoming frame:
Is there a way to retrieve them as 2 frames, as they have been really emitted on the ethernet?
Short answer: no
TCP is a stream socket, you have to handle yourself data packet begin/end detection.
Or you have to use UDP which is Datagram based. -
@KroMignon said in QTcpSocket concatenation of incoming frame:
Or you have to use UDP which is Datagram based.
but that can also arrive in parts!
-
@KroMignon said in QTcpSocket concatenation of incoming frame:
Nope, with UDP you are sending and receiving Datagram. You will receive the complete Datagram or nothing, but never a partial Datagram.
You know what, I may have interpreted all that UDP noise in my network as partial datagrams
-
@J-Hilk said in QTcpSocket concatenation of incoming frame:
You know what, I may have interpreted all that UDP noise in my network as partial datagrams
I am not sure to understand what you are saying :'(
Of course, if you are sending a large datagram it will be cut in several IP messages (this is called fragmentation).
But, on UDP level, you will only got the UDP message when all fragments are received from IP and reassembled.With TCP, there is no fragmentation, because the chunk size if adapted to match to IP payload.
-
@jsulm said in QTcpSocket concatenation of incoming frame:
@modelvincent said in QTcpSocket concatenation of incoming frame:
Is there a way to retrieve them as 2 frames, as they have been really emitted on the ethernet?
Why? You should never depend on such details, instead implement a protocoll. TCP is a stream, it is up to TCP/IP stack to split sent data in packets and accumulate them again on receiver side.
@jsulm unfortunately I have no choice, that's how the system is made.
In normal state, there is another software using low level access written in C (not Qt) that is retrieving the frame, there is no concatenation, but my Qt software is a test program that should take place of this C written software for some test purpose, and unfortunately I really need to know the size of each frame received.
I will perhaps try to use winsock directly in a QThread instead of QTcpSocket if there is absolutly no way do have this information with QTcpSocket...
-
@modelvincent said in QTcpSocket concatenation of incoming frame:
I will perhaps try to use winsock directly in a QThread instead of QTcpSocket if there is absolutly no way do have this information with QTcpSocket...
I suspect that might turn out to be required. If you really need this level of detail, why not look at the Qt source code to see what it does?
-
@modelvincent said in QTcpSocket concatenation of incoming frame:
Is there a way to retrieve them as 2 frames, as they have been really emitted on the ethernet?
No, and not even with WinSock API. Fix your code.
-
@modelvincent said in QTcpSocket concatenation of incoming frame:
I will perhaps try to use winsock directly in a QThread instead of QTcpSocket if there is absolutly no way do have this information with QTcpSocket...
You are misunderstanding how TCP/IP stack works.
As written before, TCP is a stream socket. When writing data on it, they will be stored at TCP stack level and passed to IP level when:- "enough" data is available to reduce transfer overhead
- until given time windows is elapsed
- flush() is forced on socket
And there are also some optimizations on receiver level to reduce CPU usage (eg. merging too closed data payload before triggering events).
So there is no really chance to got data packets on receiver side as they are transmitted by sender side. This is the way TCP is working.
If you know that your message size is 16 byte long, why to simply take 16 byte from the input buffer?
-
@KroMignon Because my packets haven't all the same saize.
I've made a workaround on my protocol now, so the problem is bypassed, however, there is still something that I don't understand , itis that WireShark is able to see 2 frames of 16 bytes, even if on receiver side I see only 1 32 bytes frame.
-
@modelvincent said in QTcpSocket concatenation of incoming frame:
I've made a workaround on my protocol now, so the problem is bypassed, however, there is still something that I don't understand , itis that WireShark is able to see 2 frames of 16 bytes, even if on receiver side I see only 1 32 bytes frame.
Again, there is no link between network transmission packet size and what TCP/IP stack will sent back.
There can be 10 packets exchanges on socket and only 1 socket event to inform data are available.
TCP is a stream socket, so why should it trigger too often an event when data arrives?
This would have a too high CPU time cost.Depending on you operating system and TCP/IP stack there will be some parameters you could change to adapt the default behavior, but without any guarantee of success!