According to WikiPedia “TCP provides reliable, ordered, error-checked delivery of a stream of octets between programs running on computers connected to an intranet or the public Internet.”.
It provides a reliable delivery of a “stream” of octets, not a sequence of “packets”.
That’s the reason most ISO-8583 wire protocol implementations use some kind of message boundary delimiters, typically using a header with a length indicator or some markers such as ETX character.
So the PADChannel was a tough packager to write, and that’s the reason why ISOPackager has a stream based unpack method and all ISOFieldPackager implementations have stream based unpack operations, to read the message on-the-fly.
public void unpack (ISOComponent m, InputStream in);
When you send message over TCP/IP, you can’t guarantee that the message will be transmitted in a single IP packet and will be available entirely in a single socket ‘read’ operation on the receiving end. You just can’t. Here are some reasons why:
- The TCP/IP stack on your machine may join together a couple messages in a single packet if it fits its MTU
- Intermediate routers/firewalls may split your messages in smaller packets if their MTU is smaller (we found some very small MTUs in dedicated satellite links and GPRS networks).
- You could be lucky and your message may fit a single TCP/IP packet all over the way, but for some reason, the receiving application could be busy or had a very short performance glitch, so when it arrives to the socket read operation, perhaps there are more than one message waiting. That’s the reason why you see the Recv-Q column in a ‘netstat’ command going up and down.
- There could be some packet loss so the sender TCP/IP stack needs to resend a message and could assemble multiple packets in a single bigger one
The list goes on, I recommend you read Uyless Black’s TCP/IP books.
But with all that said, we regularly find people imagining that an ISO-8583 message transmitted on one end will arrive on a single socket read at the other end. Probably legacy implementations migrated from X.25 (where that was true) to TCP/IP without designing any message boundary delimiter strategy.
There’s no solution to that, but we found this issue impossible to explain to some network admins, so we provided a very limited work around that just works on highly reliable networks with low traffic and good performance on the receiving end, adding a small ‘delay’ after we send a message so that we can pray that the TCP/IP stack and intermediate network could hopefully deliver the message in a single packet.
So PADChannel now has a ‘delay’ property (expressed in millis). If you’re facing this problem, I’d use 100ms as a starting value.