PDA

View Full Version : Packet getting fragmented when sending over QTcpSocket



arturo182
2nd June 2009, 22:37
I'm trying to write a single class to support XMPP protocol, it's packets are XML nodes.
I'm using QTcpSocket for connection with the server, but sometimes when I get a big packet the readReady signal is emited twice and I get the packet fragmented. What's the best way to bypass this? I know I can have a buffer that I write all incoming data to and process the nodes when they are done, but i this the best and most optimal way? I'm quite new to Qt so it's possible I'm missing something, I'm learning new things every day.

Fragmentation with XMPP is not even half as confuing as fragmentation with a binary protocol. I'm also trying to write a class to support Gadu-Gadu (polish IM protocol) and it's packages are binary - there's always a "header" packet that tells me what type of packet I'm going to get next and what' it's size and then I get the packet, but sometimes it also get's fragmented. I haven't try to bypass this by using a buffer cause it's not easy finding out where one packet ends and another header starts.

Any help appreciated.

arturo182
4th June 2009, 15:20
anybody? :(

wysota
24th July 2009, 21:13
I'm using QTcpSocket for connection with the server, but sometimes when I get a big packet the readReady signal is emited twice and I get the packet fragmented. What's the best way to bypass this? I know I can have a buffer that I write all incoming data to and process the nodes when they are done, but i this the best and most optimal way? I'm quite new to Qt so it's possible I'm missing something, I'm learning new things every day.
You can either buffer the data in your application or use QXmlStreamReader for parsing the xml. It can operate on incomplete data - when more data is ready, you can ask it to continue where it left off. There is also a third choice - do nothing (ignore readyRead()) until the whole package of data arrives. If the messages are small enough, they will fit into the internal buffer so you don't have to keep making room for more data.



Fragmentation with XMPP is not even half as confuing as fragmentation with a binary protocol.
It's not fragmentation, it's analog world where things don't happen in an instant.

Kill3rReaper
25th July 2009, 13:07
a third choice - do nothing (ignore readyRead()) until the whole package of data arrives. If the messages are small enough, they will fit into the internal buffer so you don't have to keep making room for more data.
But this method will freez program, until rest of package will not receive to us, right?

P.S: Sorry for my poor english...

wysota
25th July 2009, 13:28
But this method will freez program, until rest of package will not receive to us, right?

No, why? Socket operations are asynchronous, they don't freeze your gui.

Kill3rReaper
25th July 2009, 19:37
Look at this example:


<message from="smn@jabber.com"><body>Lorem ipsum... (and a lot of text)</body></message>

If this verse will longer than, for example, 2000 bytes, then this message, will be broken in the, again for example :P, 1500 byte. Rest 500 bytes will be send in new packet. So, I don't know, where my message ends, because between tags <body> and </body> I can send XML code, which can have inside tag </body> or </message> :(
I hope you understand my english. If no, can I write to you pm in polish language? :D

wysota
25th July 2009, 19:41
The fact that it comes in parts is meaningless and has nothing to do with freezing anything. If you know what you expect then you can wait until your expectations are filled. Doing this by ignoring the data is probably not the best idea but it is possible. A better way is to read the pending data (thus freeing the incoming buffer), scanning that data for end of message (which is easy in your case) and either processing the data or waiting until more comes in. Remember that you can also get more than one message in a single go, you need to handle situations like that as well.

Kill3rReaper
25th July 2009, 20:13
Ehhhh, I thought there was some other way to do it :(
Anyway, thank you for answer!
Czesc ;)

wysota
25th July 2009, 23:01
Ehhhh, I thought there was some other way to do it

Sure there is. Use QXmlStreamReader.

Kill3rReaper
5th August 2009, 00:53
Ehhh... I just was writing new class for XML packets, when I try to write something XML to <body> </body> section... Code between these tags is interpretting by my algorism... When I was using QDomElement, I did't have got that problem :( What I can do?

faldzip
5th August 2009, 08:13
and what is the problem exactly?

Kill3rReaper
5th August 2009, 17:22
My english sux very much...
For example:

<message from='test@jab.com/Jabber' type='chat' xml:lang='pl' to='test@jabbim.pl'><active xmlns='http://jabber.org/protocol/chatstates'/><body>Hey!</body></message>
If I change body section to: "Hej <someth" my application freezes.

wrdieter
5th August 2009, 18:54
My english sux very much...
If I change body section to: "Hej <someth" my application freezes.

I have not used the XML parser in Qt before, but other XML parsers would interpret the '<' symbol in the body as the opening to a tag. The parser would then read until it finds a closing '<' tag. Try converting the '<' to "&lt;" and see if your program still hangs.

You can do the string conversion manually or for '<' and '>' with QString's replace string functions. There might be a method in one of the XML classes to quote characters that are meaningful to XML for you.

arturo182
5th August 2009, 23:08
Well, he can't change the packet cause that's the way the server sends it.

My solution would be if you see the opening "body" tag, treat everything that follows as text untill you reach closing "body" tag. But that's not perfect cause someone could be chatting about HTML and send </body> and that would screw the parser up.

Kill3rReaper
5th August 2009, 23:11
I have not used the XML parser in Qt before, but other XML parsers would interpret the '<' symbol in the body as the opening to a tag. The parser would then read until it finds a closing '<' tag. Try converting the '<' to "&lt;" and see if your program still hangs.

You can do the string conversion manually or for '<' and '>' with QString's replace string functions. There might be a method in one of the XML classes to quote characters that are meaningful to XML for you.
It's good idea :)
I thought about use QDomElement class to solve this problem, but your solution sounds good :)
P.S: I know that the XML parser interprets '<' symbol as the opening tag, but I could not cope with this ;/