2
votes

I'm having some trouble to parse a TCP packet from a socket...

In my protocol, my messages are like this:

'A''B''C''D''E'.........0x2300

'A''B''C''D''E' --> start message pattern

0x2300 --> two bytes end message

But due to the Nagle's algorithm, sometimes my messages are concatenated like:

'A''B''C''D''E'.........0x2300'A''B''C''D''E'.........0x2300'A''B''C''D''E'.........0x2300

I already tried to setNoDelay() to true but the problem persists.

I have the message in a byte[].

How could I split my messages to be parsed individually?

PS: For now I am able to get the first message but the others are lost...

3
you mean two messages put in one byte array?Nikolay Kuznetsov
TCP is a stream, there are no guarantees that a read will give data in the same lengths that the data was written in. This is not a bug and you can not turn it off.Erik Ekman
There is no such thing as a TCP packet. You are parsing the unpredictable and uncontrollable bit of the stream that arrived in the last read. It isn't the same thing, as there is no such thing.user207421

3 Answers

3
votes

Just loop through you received data and check for end-markers. When found set a start index to the next package and continue searching. Something like this:

int packageStart = 0;
for(int i = 0; i < data.length - 1; i++) {
  if(data[i] == 0x23 && data[i + 1] == 0x00) {
      // Found end of package
      i++;
      processPackage(data, packageStart, i);
      packageStart = i;
  }
  // At this point: from packageStart till data.length are unprocessed bytes...

As noted, there might be some left over data (if data did not end with the end-marker). You might want to keep it, so you can prepend it to the next batch of received data. And thus preventing data-loss due to chopped up TCP/IP packages.

2
votes

You have to think of it as parsing a continuous stream of bytes. Your code needs to identify the start and end of a message.

Due to the way packets get sent, you may have a complete message, multiple messages, a partial message, etc. You code needs to identify when a message has begun and keep reading until it has found the end of a message or in some instance, when you've read more bytes than your max message size and you need to resync.

I've seen some comm managers drop and reestablish the connection (start over) and others throw away data until they can get back in sync. Then you get into the fun of whether you need guaranteed delivery and retransmission.

The best protocols are the simple ones. Create a message header which contains say an SOH byte, a two byte message length (or whatever is appropriate), a 2 byte message type and 1 byte message subtype. You can also end the message with any number of bytes. Look at an ASCII chart, there's a number of Hex bytes 00-1F that are pretty standard since the terminal days.

No point in reinventing the wheel here. Makes it easier, because you know how long this message should be instead of looking for patterns in the data.

-2
votes

It sounds like you need to treat it like a Byte Stream and buffer the packets until you see your EOF code 0x2300.