0

I am reading TCP packets that I use to display an image. Each packet is supposed to have a 1025 length. And each time, I get 128 lines, I draw an image.

SO I begin by initializing

s = new Socket(ip, port);
stream = s.getInputStream();
byte[] tmpBuffer = new byte[1025];
byte[] finalBuffer = new byte[128 * 1025];
int count_lines =0

and then I read stream by stream of length 1025,

while((read = stream.read(tmpBuffer, 0, tmpBuffer.length)) != -1){
    System.arraycopy(tmpBuffer, 1, finalBuffer, count_lines * 1025, 1025); 
    count_lines++; 
    if(count_lines == 128) break;
}

The problem is when I log the read integer, I get a bunch of 1025 but sometimes (apparently randomly) 423 or 602 (noticing that 423+602=1025)

Am I going wrong with the TCP reading or is there a problem on the server side ?

6
  • Yes, you are going wrong. TCP packets are treated as data stream and the separation won't be preserved. Commented Mar 19, 2016 at 14:00
  • @MikeCAT thank you, is there a way to get them ? Commented Mar 19, 2016 at 14:01
  • If you know you will receive 1025 bytes of data, just read that many bytes. If stream.read() returns less, you have to read again. Commented Mar 19, 2016 at 14:03
  • @markspace so you mean read = stream.read(tmpBuffer) and if readis not equal to 1025, then I read again ? Commented Mar 19, 2016 at 14:07
  • Yup. Count the total bytes, return it it reaches 1025. Commented Mar 19, 2016 at 14:07

1 Answer 1

1

Am I going wrong with the TCP reading or is there a problem on the server side ?

In TCP you have only a stream of bytes. You have messages nor control over packets which are typically no more than 1532 bytes long.

You have to have your own protocol to handle sending of messages.

inputStream.read(buffer) will read between 1 byte and buffer.length and you can't ignore the actual length read as you are doing.

If you want to read into a buffer of a known length, you can use

DataInputStream dis = new DataInputStream(socket.getInputStream());
byte[] finalBuffer = new byte[128 * 1025];
dis.readFully(finalBuffer);

The readFully reads as much as it can at a time until the byte[] has been fully read.

A more flexible protocol is to send the length first.

public static void write(DataOutputStream out, byte[] bytes) {
    out.writeInt(bytes.length());
    out.write(bytes);
}

public static byte[] read(DataInputStream in) {
    int length = in.readInt();
    byte[] bytes = new byte[length];
    in.readFully(bytes);
    return bytes;
}

This way, whatever length of data you send, you will recieve in the same manner.

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

2 Comments

thank you, @markspace told me that I should put read = stream.read(tmpBuffer) and reading byte if and only if read is equal to 1025. Is that still correct ?
@Newben That is not what he/she said. He said if you read less than 1025, you have to read more.

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.