0

I am using Java for socket communication. The server is reading bytes from the client like this:

InputStream inputStream;
final int BUFFER_SIZE = 65536;
byte[] buffer = new byte[BUFFER_SIZE];
String msg="";

while (msg.indexOf(0)==-1 && (read = inputStream.read(buffer)) != -1)
{
    msg += new String(buffer, 0, read);
}
handleMessage(msg)

There is a problem when a client is sending multiple messages at once the server mixes the messages e.g.

MSG1: <MyMessage><Hello/>nul
MSG2: </MyMessage><MyMessage><Hello again /></MyMessage>nul

So the tail of Message 1 is part of Message 2. The null represents the java nul symbol.

Why does the inputstream mix the messages?

Thanks in advance!

1
  • Show us the code for both sides of the communication. Commented Mar 24, 2011 at 10:26

4 Answers 4

1

You are doing the wrong comparison. You check if there is a \0 anywhere in the String, and then believe it is a single message. Wrong. In fact, in the second example, the \0 comes twice.

You should do it differently. Read from the Stream in char by char (Using a wrapping BufferedInputStream, else the performance will be awful), and skip when the \0 is reached. Now the message is complete, and you can handle it.

InputStream bin = new BufferedInputStream(inputStream);
InputStreamReader reader = new InputStreamReader(bin);
StringBuilder msgBuilder = new StringBuilder();
char c;
while ( (c=reader.read()) != -1 ) 
{
    msgBuilder .append(c);
}
handleMessage(msgBuilder.toString())

Even better would be using the newline character for line separation. In this case you could just use the readline() functionality of BufferedReader.

Sign up to request clarification or add additional context in comments.

5 Comments

I used to read one byte at a time but it turned out to be to slow causing delays. Therefore I changed the code to read chunks of bytes. I also tried the newline method but I had problems with it because I am using Flash on the client site and there was an issue in terminating the line.
@doorman, BufferedInputStream does the buffering for you improving efficiency.
@Daniel, are you sure c can be -1 as its unsigned. ;)
After some experiments I am again running into delay problems. It seems that the buffering is not working properly. In my project multiple clients are connected and they are all sending messages every second. This was not an issue when reading chunk of bytes in the code example I wrote in my question. Do I need to configure the buffering so it will handle more traffic when reading the stream char-by-char?
@doorman: No, it should work regardless of the number of clients. Maybe the bug is somewhere else? Use Wireshark to analyse the sent data and validate it is correct.
0

Sockets and InputStream are only a stream of bytes, not messages. If you want to break up the stream based on a char like \0 you need to do this yourself.

However, in your case it appears you have a bug on your sending side as the \0 isn't the right places and it is highly unlikley to be a bug on the client side.

btw: Using String += is very inefficient.

1 Comment

String is immutable so on every loop it is called, it take a copy of the original String, appends the new String and creates the combined String. See @Daniel's solution for an alternative.
0

The data you read from InputStream will come in as it's available from the OS and there's no guarantee on how it will be split up. If you're looking to split on new lines you might want to consider something like this:

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

And then use reader.readLine() to get each line as a String that's your message.

2 Comments

I tried the readline method but I am using Flash on the client site and there was an issue with correctly terminating the line.
Are you able to send anything between messages to delimit them? It appears that you're relying entirely on XML to that right now. That's going to make it a bit trickier to split them up on the Java side.
0

I think your problem is in your approach:

There is a problem when a client is sending multiple messages at once

Sockets in general just get chunks of bytes and the trick is in how you send them, how do you mark start/end of a message and how do you check it for errors (quick hash can do a lot of good) so the behaviour is fine in my eyes, you just need to work on your messaging if you really need to send multiple messages at once.

Sockets will control if your message is integral physical wise but what is IN the message is your concern.

2 Comments

I am terminating messages using 0 on the client site
I would suggest wrapping each message with a start char, followed by a quick hash of the message content, followed by the message, followed by an end char. Then you can recognise start/stop of each message recognising them by the hash (think of it as a tag of a message) and if the hash is not right with what you get then you can ask the client for a re-send if you can communicate back to the client.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.