I'm making a Server that gets packages at 64 kb size.
int length = 65536;
byte[] bytes = new byte[length];
int pos = 0;
while(pos < length -1)
{
System.out.println("Before read");
pos += dis.read(bytes, pos, length-pos);
System.out.println(""+pos+" >> "+ length);
}
This is the code I use to read all bytes from the socket. Dis is a InputStream.
When I run the code 1 out of n goes wrong. The code only receives 52964 bytes instead of 65536 bytes.
I also checked the C code and it says it send 65536 bytes.
Does someone know what I'm doing wrong?
This is yet another case where Jakarta Commons IOUtils is a better choice than writing it yourself. It's one line of code, and it's fully tested. I recommend IOUtils.readFully() in this case.
If it does not read the entire buffer, then you know that you're not sending all the content. Perhaps you're missing a flush on the server side.
InputStream.read() returns the number of bytes read or -1 if the end of the stream has been reached. You need to check for that error condition. Also, I suspect your while(..) loop is the problem. Why are you calling it pos as in position? You may be terminating prematurely. Also, ensure that your C code, whatever it is doing, is sending properly. You can examine the network traffic with a tool like Wireshark to be sure.
What do you mean it "goes wrong"? What is the output? It can't be exiting the loop before reading the full 64 KB, so what really happens?
Also, it's better to save the return value of the I/O call separately and inspect it, before assuming the I/O was successful. If that's DataInputStream.read(), it returns -1 on error.
Your code is incorrect as it doesn't check for -1.
This is a case for using DataInputStream.readFully() rather than coding it yourself and getting it wrong.
Related
The client reads the status byte in the loop while it is equal to 0x01:
do {
input.read(magicWord); // ALWAYS THE SAME BYTE AFTER THE SERVER IS GONE
if (magicWord[0] == (byte) 0xFF)
break;
// retrieve the progress
byte[] cur = new byte[4];
input.read(cur);
// and set the progress bar
progressBar.setValue(ByteBuffer.wrap(cur).getInt());
} while (!isCancelled());
But if the server crashes (for example by SIGKILL) while the client is in this loop, the client keeps getting the last magickWord sent by the server over and over again (and gets into the endless loop). Even setting SO_TIMEOUT doesn't solve the problem. How should the client detect a server failure?
It doesn't read anything at all. input.read(magicWord) return -1. You 0xFF byte in your buffer since previous read (read method doesn't clear buffer).
That call to read returns the number of bytes read. You do not check that result.
And you do not clear your read buffer - thus you keep seeing the same bytes all the time.
Your code is wrong.
You must check the return value of the read call. Look it up in the documentation and write your code accordingly.
We have a Java code talking to external system over TCP connections with xml messages encoded in UTF-8.
The message received begin with '?'. SO the XML received is
?<begin>message</begin>
There is a real doubt if the first character is indeed '?'. At the moment, we cannot ask the external system if/what.
The code snippet for reading the stream is as below.
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
int readByte = reader.read();
if (readByte <= 0) {
inputStream.close();
}
builder.append((char) readByte);
We are currently trying to log the raw bytes int readByte = inputStream.read(). The logs will take few days to be received.
In the mean time, I was wondering how we could ascertain at our end if it was truly a '?' and not a decoding issue?
I suspect strongly you have a byte-order-mark at the beginning of your doc. That won't render as a valid character, and consequently could appear as a question mark. Can you dump the raw bytes out and check for that sequence ?
Your question seems to boil down to this:
Can we ascertain the real value of the first byte of the message without actually looking at it.
The answer is "No, you can't". (Obviously!)
...
However, if you could intercept the TCP/IP traffic from the external system with a packet sniffer (aka traffic monitoring tool), then dumping the first byte or bytes of the message would be simple ... requiring no code changes.
Is logging the int returned by inputStream.read() the correct way to to analyse the bytes received. Or does the word length of the OS or other environment variables come into picture.
The InputStream.read() method returns either a single (unsigned) byte of data (in the range 0 to 255 inclusive) or -1 to indicate "end of stream". It is not sensitive to the "word length" or anything else.
In short, provided you treat the results appropriately, calling read() should give you the data you need to see what the bytes in the stream really are.
My goal is to send different kind of messages from client to server, and it will be text based. The thing I am uncertain of is how to del with partial reads here. I will have to be sure that I get a whole message and nothing more.
Do anyone have experience with that?
Here is what I have so far:
private void handleNewClientMessage(SelectionKey key) throws IOException {
SocketChannel sendingChannel = (SocketChannel) key.channel();
ByteBuffer receivingBuffer = ByteBuffer.allocate(2048);
int bytesRead = sendingChannel.read(receivingBuffer);
if (bytesRead > 0) {
receivingBuffer.flip();
byte[] array = new byte[receivingBuffer.limit()];
receivingBuffer.get(array);
String message = new String(array);
System.out.println("Server received " +message);
}
selector.wakeup();
}
But I have no way of "ending" the message and be certain to have one full message.
Best regards,
O
You can never be sure you won't read more than one message unless you only read one byte at a time. (Which I don't suggest).
Instead I would read as much as you can into a ByteBuffer and then parse it to find the end of the message e.g. a newline for text.
When you find the end of a line extract it and convert it to a String and process it. repeat until you have a partial message (or nothing left)
If you find you have only part of a message, you compact() (if position() > 0) when you have and try to read() some more.
This will allows you to read as many messages at once as you can but can also handle incomplete messages.
Note: You will need to keep the ByteBuffer for a connection so you know what partial messages you have read before.
Note: this is will not work if you have a message which is larger than your buffer size. I suggest using a recycled direct ByteBuffer of say 1+ MB. With direct ByteBuffers only the pages of the ByteBuffer which are used get allocated to real memory.
If you are concerned about performance I would re-use your byte[] where possible. You only need to re-allocate it if you need more space than you have already.
BTW, You might find using a BufferedReader with Plain IO is much simpler to use, but still performance well enough.
I'm encountering this exception a lot in a piece of code I have, and it's happening when I call readFully. I don't understand how it can happen though, because readFully is supposed to block until len bytes are available. If it knows that that many bytes are available, how can it then later meet an EOF?
And how can I get around this issue? (I'm reading the first 3 bytes to get the length (TL part of TLV) and then encountering the issue sporadically when reading the V).
Thanks
The documentation says:
throws: EOFException - if this input stream reaches the end before reading all the bytes.
So this behavior is expected if the length you send is not correct (i.e. is larger than the actual length), or if the sender closes the stream before having written all the bytes.
I am reading in arbitrary size file in blocks of 1021 bytes, with a block size of <= 1021 bytes for the final block of the file. At the moment, I am doing this using a BufferedInputStream which is wrapped around a FileInputStream and code that looks (roughly) like the following (where reader is the BufferedInputStream and this is operating in a loop):
int availableData = reader.available();
int datalen = (availableData >= 1021)
? 1021
: availableData;
reader.read(bufferArray, 0, datalen);
However, from reading the API docs, I note that available() only gives an "estimate" of the available size, before the call would 'block'. Printing out the value of availableData each iteration seems to give the expected values - starting with the file size and slowly getting less until it is <= 1021. Given that this is a local file, am I wrong to expect this to be a correct value - is there a situation where available() would give an incorrect answer?
EDIT: Sorry, additional information. The BufferedInputStream is wrapped around a FileInputStream. From the source code for a FIS, I think I'm safe to rely on available() as a measure of how much data is left in the case of a local file. Am I right?
The question is pointless. Those four lines of code are entirely equivalent to this:
reader.read(buffer, 0, 1021);
without the timing-window problem you have introduced between the available() call and the read. Note that this code is still incorrect as you are ignoring the return value, which can be -1 at EOS, or else anything between 1 and 1021 inclusive.
It doesn't give the estimated size, it gives the remaining bytes that can be read. It's not an estimate with BufferedInputStream.
Returns the number of bytes that can
be read from this input stream without
blocking.
You should pass available() directly into the read() call if you want to avoid blocking, but remember to return if the return value is 0 or -1. available() might throw an exception on buffer types that don't support the operation.