简体   繁体   中英

InputStream on socket reads zeros

I try receive a raw binary packet on my server side. I have control over the data format and specified the first 4 bytes of a packet to describe the length of the packet (it is an int value converted to byte[] and back). This works very well, I get the correct numbers (I can also monitor and check the client side). Here is the code:

is = connectionSocket.getInputStream();
byte[] intArray = new byte[4];
//read the 4-byte int value to array
is.read(intArray, 0, 4);
int packetLength = ByteBuffer.wrap(intArray).getInt();

I then want to read the package (excluding the length-header) to a custom-fit byte array:

byte[] packet = new byte[packetLength];//make a buffer ready
is.read(packet, 0, packetLength);//read the whole packet to array

If the sent byte[] has a length of 1444 or less, everything works fine. But packets beyond this limit won't be received properly. The packet-array will be filled correctly with data at the beginning, but after the limit, there are only zeros until the end like this

Positon: ...|1440|1441|1442|1443|1444|1445|1446|1447|.........|packetLength-1
Data:    ...| 59 |-73 | 125| -3 |  0 |  0 |  0 |  0 |..zeros..| 0

From my days as a 13-years-old-wannabe-internet-tuning-master I can still remember, that there is a standard MTU (maximum transmission unit) of about 1500 bytes on Windows machines. Indeed my receiving network adapter has an MTU of 1500. That's suspiciously close to 1444, so I increased the MTU, but sadly with no results. Java should not bother me with such low-level stuff, but maybe this isn't a coincidence. btw, the client is an Android smartphone, receiver a Windows 7 machine.

Does anybody have another idea or even better a solution?

You're ignoring the count returned by read(), and assuming that it filled the buffer. It isn't obliged to do that. See the Javadoc.

The simple way to do what you're doing, correctly, is to use DataInputStream.readInt(), followed by readFully().

NB Contrary to your comment, merely adding int size = didn't have that effect at all, of course. It isn't possible. What changed was the timing, for some other reason, so that four bytes really arrived.

Finally I found out about the race-condition-like nature of read myself, but thanks for the help and clarification. I noticed it when I observed that setting debug stops solved the problem, that gave the buffers time to do their job. Using DataInputStream is also much nicer to code, thanks again. Here is my (hopefully) final solution:

DataInputStream dis = new DataInputStream(connectionSocket.getInputStream());
int packetLength = dis.readInt();
byte[] packet = new byte[packetLength];//make a buffer ready       
dis.readFully(packet);//read full packet to buffer

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM