views:

142

answers:

4

We're having a bizarre problem with Indy10 where two large strings (a few hundred characters each) that we send out one after the other using TCP are appearing at the other end intertwined oddly. This happens extremely infrequently.

Each string is a complete XML message terminated with a LF and in general the READ process reads an entire XML message, returning when it sees the LF.

The call to actually send the message is protected by a critical section around the call to the IOHandler's writeln method and so it is not possible for two threads to send at the same time. (We're certain the critical section is implemented/working properly). This problem happens very rarely. The symptoms are odd...when we send string A followed by string B what we received at the other end (on the rare occasions where we have failure) is the trailing section of string A by itself (i.e., there's a LF at the end of it) followed by the leading section of string A and then the entire string B followed by a single LF. We've verified that the "timed out" property is not true after the partial read - we log that property after every read that returns content. Also, we know there are no embedded LF characters in the string, as we explicitly replace all non-alphanumeric characters in the string with spaces before appending the LF and sending it.

We have log mechanisms inside the critical sections on both the transmission and receiving ends and so we can see this behavior at the "wire".

We're completely baffled and wondering (although always the lowest possibility) whether there could be some low-level Indy issues that might cause this issue, e.g., buffers being sent in the wrong order....very hard to believe this could be the issue but we're grasping at straws.

Does anyone have any bright ideas?

+3  A: 

Are you using TCP or UDP? If you are using UDP, it is possible (and expected) that the UDP packets can be received in a different order than they were transmitted due to the routing across the network. If this is the case, you'll need to add some sort of packet ID to each UDP packet so that the receiver can properly order the packets.

Jason Swager
Should have mentioned it was TCP. I've edited the question.
Jim
+3  A: 

You could try Wireshark to find out how the data is tranferred. This way you can find out whether the problem is in the server or in the client. Also remember to use TCP to get "guaranteed" valid data in right order.

Harriv
A: 

Do you have multiple threads reading from the same socket at the same time on the receiving end? Even just to query the Connected() status causes a read to occur. That could cause your multiple threads to read the inbound data and store it into the IOHandler.InputBuffer in random order if you are not careful.

Remy Lebeau - TeamB
We refactored the code a bit and then upgraded to the most recent Indy10 (Tiburon branch) and the problem has not recurred. I didn't think there were any thread issues as there is a single thread whose job it is to do all of the reading, and then place received data on a threadsafe queue for the rest of the application to access. However, I will review the code one more time for potential thread issues.
Jim
If you have a sole thread doing all of the reading (including all Connected() calls), then the only way Indy can receive data out of order is if the sender sent the data out of order to begin with.
Remy Lebeau - TeamB
A: 

Have you checked the Nagle settings of the IOHandler? We had a similar problem that we fixed by setting UseNagle to false. In our case sending and receiving large amounts of data in bursts was slow due to Nagle coalescing, so it's not quite the same as your situation.

Alan Clark