reading inputstream of a socket - java

I have snippet
try {
is = new BufferedReader(new inputStreamReader(getSocket().getInputStream()));
}
catch(IOException e) {}
while(true) {println(is.readLine());}
Basically, I'm tring to println every single message that is sent to the input stream of the socket returned from getSocket().
My question is:
If there is no message sent to the socket, what value is returned
from calling the readLine() method? Is it the null value or a null
string (i.e. "") or is it something else?
When a message has been
sent and has been printed out, what happened to the input stream of
the socket then? Is it emptied out?
Do we need a way to check to
only call the println() method only when the input stream HAS
something to print out?

If nothing is sent through the stream - there is nothing to read yet. Your reader is just waiting.
It is emptied out only from the data you have received.
You should have the while(true) loop which is trying to read the line from the stream. You do not have to check anything.
If the socket is closed at the second side, reader is reading null. If the second side has exited without closing the socket, you get IOException.

If there is no message sent to the socket, what value is returned from calling the readLine() method? Is it the null value or a null string (i.e. "") or is it something else?
Neither. It blocks.
When a message has been sent and has been printed out, what happened to the input stream of the socket then? Is it emptied out?
No. The data received has been removed from it. There may be further pending data waiting be read.
Do we need a way to check to only call the println() method only when the input stream HAS something to print out?
No. It blocks until a line has been received, end of stream occurs, or an IOException is thrown.
Your read loop isn't correct. It doesn't detect end of stream. The usual way to write it is:
while ((line = in.readLine()) != null)
// ...

Related

How to detect end of Input Stream from Socket using BufferedInputStream?

I'm trying to read and input from a Socket in Java and then proccess it by calling a function. I must read by byte and not by text because reading as text give some erros because of the requests coming from client. So I decided to use the class BufferedInputStream. The problem is that the end of a request is not being detected. I guess that this is because the stream is not ending just being hanged or something...
According to the documentation, the read() function returns a byte read from the stream or -1 if the stream has ended. So, my code reads byte by byte, joins it in a string, and then, when the stream has ended, sends the string to be proccessed (or at least, was supposed to do this). Here is the code:
BufferedInputStream reader = new BufferedInputStream(socket.getInputStream());
int dt;
String cmd = "";
while( (dt = reader.read()) >= 0){
cmd += (char)dt == '\n' || (char)dt == '\r' ? ' ' : (char)dt; // add each byte read to the string
System.out.println(cmd);
}
processaInput(cmd);
The problem is that the function processaInput is never being called like if the program was stuck in the loop. But even more stranger is that is not stuck on the loop because the system.out.println stops being called after the stream has ended. By the way, this while is being ran in a Thread (run() function), don't know if this can mess up so I added this last info here. Anyway, what am I missing here? Thanks.
Edit: There is no Client side code because I'm using the app POSTMAN from google to test it, so it is just sending HTTP request to my program.
You are conflating 'end of request' with 'end of stream'.
'End of stream' on a socket means the peer has closed the connection. No end of stream, no peer close. If you plan to write a response back down this socket, it is therefore incorrect to try to read it to end of stream first.
You are trying to read a single request, in which case you need something in your application protocol to tell you when you have it all: lines; a length word prefix; a self-describing protocol like XML; STX/ETX; type-length-value; ...
In this case if the protocol is HTTP you need to implement the Content-length header: recognise it, read to the end of the headers, then read exactly that many bytes from the stream, e.g. with DataInputStream.readFully().

Regarding data read from TCP connection

I am making a client socket connection with a hardware device. I am sending a command to this connection to be process by hardware. Now as a acknowledgment or as a reply, the hardware sends a response.
The application sends a command to the connection periodically say in 10 seconds.
Now there exists a problem randomly that the response won't gets synchronized with the sent command from the application. I was thinking of this as hardware specific but to my surprise, when I see the response by connecting putty to the same hardware at same port, I can see that response always gets synchronized. This looks like putty under the hood using some criteria to map the request to response.
Below is the programming steps that I am using to send a command to hardware device:-
Socket clientSocket = new Socket(<IPADDRESS>, 4001);
DataOutputStream outToServer = new DataOutputStream(
clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
while (true) {
try {
//Get command randomly from array enums for test
Random r = new Random();
Commands[] array = Commands.values();
String command = (String) array[r
.nextInt(Commands.values().length)].getCommand();
outToServer.writeBytes(command);
Thread.sleep(500);
while (!inFromServer.ready()) {
}
System.out.println("COMMAND "+command+", SERVER RESPONSE: "
+ inFromServer.readLine());
Thread.sleep(1500);
} catch (SocketTimeoutException se) {
//Handle Exception
} catch (SocketException se) {
//Handle Exception
}
Can anybody gives a advice how the synchronization of response with request can be achieved as mechanism like putty?
Putty doesn't know any more about your device than you do. The problem is in your code. Get rid of the ready() test and the sleep(). Just call readLine(), if you can be sure that the device sends lines, otherwise just call InputStream.read().
Remove the thread sleep, and rewrite read like this:
String line;
while ((line = inFromServer.readLine()) != null) {
System.out.println("COMMAND "+command+", SERVER RESPONSE: "
+ line);
}
This code can still hang, if the device sends the last message without the newline character \n. Your original code skipped the input.
The main problem is with this line:
while (!inFromServer.ready()) {
InputStreamReader#ready is OK to use only when you have other means to know that all the data has been sent:
Tells whether this stream is ready to be read. An InputStreamReader is ready if its input buffer is not empty, or if bytes are available to be read from the underlying byte stream.
The first message will get read, but that empties the buffer, and when the second message arrives your code isn't reading anymore. You would have to have as many loops as there are messages from device, and that's not practical, at least. And in that case also, it would probably not work all the time.
On the other hand the BufferedReader#readLine:
Returns:
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
will read until all the data that was sent has been read. But if your device send no new line character, then this method will never read the line - the code will hang with all the data in the buffer. In that case you should use InputStreamReader#read as EJP suggested:
Returns:
The character read, or -1 if the end of the stream has been reached
I strongly suggest that you read the IO Streams official tutorial.
Generally speaking, waiting is not done by Thread.sleep and busy waiting (executing empty statements), e.g.:
while (true) {} /*or*/ while(true);
The CPU is executing the empty statement, and it could be doing some other work while waiting on this one to complete. It is a bad practice.
If you want to know more on how to implement waiting I recommend reading the official concurrency tutorial or this one for a broader approach on the matter.

Read data from a client socket in Java

I have written the code for sending/receiving data from a client socket. The sending data step has been done successfully, but when I want to read the data from a socket, the readLine() method block program while there isn't data to be read.
This is my code:
StringBuffer document = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null)
document.append(line + "\n");
reader.close()
thanks all
I can read all received data, but readLine or read(byte[], int, int) methods block program when there is no data to read, while this method must return null/-1 in this time.
That's because the readLine() function is a blocking call, so of course it's going to block.
To be more constructive, calls to methods like readLine() should be in a separate thread so that the blocking call does not affect the rest of your code. From the class which is reading, I would recommend creating a thread purely to control reading from the socket.
I would pass a reference to the creating class so that if the thread receives information, the parent class can use it.
BufferedReader has a method called 'ready()' which returns true when data is ready to be received. If you don't want to be blocked at 'readLine()' call, check first if data is ready to be read.
Have a look at the documentation.

How should I read from a buffered reader?

I have the following example of reading from a buffered reader:
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
The code in the loop println will be executed whenever something appears in the buffered reader (input in this case). In my case, if a client-application writes something to the socket, the code in the loop (in the server-application) will be executed.
But I do not understand how it works. inputLine = input.readLine() waits until something appears in the buffered reader and when something appears there it returns true and the code in the loop is executed. But when null can be returned.
There is another question. The above code was taken from a method which throws Exception and I use this code in the run method of the Thread. And when I try to put throws Exception before the run the compiler complains: overridden method does not throw exception. Without the throws exception I have another complain from the compiler: unreported exception. So, what can I do?
When the socket on the other end is closed, the reader should return a null string. This is the condition that you are looking for. To handle the exception, wrap the reading loop in a try/catch block.
try {
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
}
catch (IOException e) {
System.err.println("Error: " + e);
}
You might find this tutorial on reading/writing from/to a socket in Java, helpful.
For your first question:
But I do not understand how it works. inputLine = input.readLine() waits until something appears in the buffered reader and when something appears there it returns true and the code in the loop is executed. But when null can be returned.
BufferedReader.readLine() does not return true upon success. It returns a String containing the line that was read. If the end of the stream is reached, it returns null.
Your second question:
The above code was taken from a method which throws Exception and I use this code in the run method of the Thread. And when I try to put throws Exception before the run the compiler complains: overridden method does not throw exception. Without the throws exception I have another complain from the compiler: unreported exception. So, what can I do?
You should wrap your code in a try/catch block. If you don't want to handle the caught exception, simply leave that part blank (not recommended)
try {
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
} catch (Exception e) {
//handle exception
}
The reader's readLine() will return a string value when it has something read, an empty string when there isn't anything yet, and null when the connection is closed.
I would recommend wrapping a try/catch around your block of code with the IO function and handle errors appropriately.
input reader is connected to the socket, which is a listener, i.e. keeps listening to incoming messages.
About your second question, you should put a try/catch block inside the method, catch the Exception and handle it. Do not re-throw it.
But I do not understand how it works. .... waits until something appears in the
buffered reader and when something
appears there it returns true
No, it returns the value of the expression (inputLine = input.readLine()), the inputLine itself. The inputLine is compared to null.
null is returned when the "EOF (End Of File)" is reached. Since this is reading from a network socket, the end of file is created when the socket is disconnected (either by the server or the client), but you will likely get an Exception before you actually see the EOF.
If this isn't for homework, you might want to look at Apache Commons IOUtils.
Assuming you don't create the BufferedReader, and just stop at the InputStream:
String results = IOUtils.toString(inputStream);
System.out.println(results);
while ((inputLine = input.readLine()) != null) {
Look at each part of the expression:
input.readLine()
Returns a String which will be null if the end of the stream has been reached (or throws an Exception on error).
inputLine = input.readLine()
Assigns this String to inputLine
((inputLine = input.readLine()) != null)
Checks that the String that was assigned is not null (end of stream).
You have received some good answers. Just catch the exception and deal with it locally. If you need to pass this on to other code but cannot since the run() method does not allow for any check exception, you can wrap the exception in a RuntimeException of some kind. If the run method is executing directly on a Thread (since it is a Runnable probably) then you should take care with re-throwing a wrapped exception.
As for the result from readLine(), it will return null when there is nothing more to read. In the case of a socket this is when the other side cleanly closes the socket (any sudden termination or unclean close would typically result in an exception in your code as the OS will send a different kind of socket close notification).
I do have one word of caution since you are wrapping a socket in a java.io.BufferedReader. You should be very careful about using this in any kind of production code.
The danger is that BufferedReader does not deal well with exceptions in the midst of reading. This is especially an issue if you have enabled a timeout on the socket so the code will receive periodic exceptions automatically from the operating system. The timeout (or other exception) could come while the buffer inside the reader is filling. If you attempt to reuse the object after the exception, it will ignore any previous contents in the buffer. The packet(s) that were previously received are silently lost and there is no way to retrieve those bytes.
Note that there are other kinds of socket exceptions that do not mean that the socket has been lost. For instance, look at the definition of java.io.InterruptedIOException. This has a public variable that reports the number of bytes successfully transferred in the most recent I/O (read or write) request. This means that the IO operation can be executed again to retrieve or send the remaining bytes for the packet.
If upon any exception your design is to immediately close the reader and socket the method will work correctly.
The proper way to read from a socket is to use the socket stream directly, use NIO (ByteBuffers and such), or use a well written network library with good abstractions over these lower level classes (several open source ones are available).

Java socket programming - stream get stuck

I am currently working on a simple proxy server, which receives http request from browser, process it, then forward it to the desire web server.
I try to get the request from the input stream of the socket connected by the browser, everything is fine except that the stream get stuck after receiving the last block of data.
My code is in fact very simple, as shown below:
ServerSocket servSocket = new ServerSocket(8282);
Socket workSocket = servSocket.accept();
InputStream inStream = workSocket.getInputStream();
byte[] buffer = new byte[1024];
int numberRead = 0;
while ((numberRead = inStream.read(buffer, 0, 1024)) != -1){
System.out.println(new String(buffer));
}
The loop simply cannot exit, even the request reception is finished.
Is there any method to workaround this problem?
Thanks in advance for any advice.
As in InputStream javadoc the method will block until the data is available or the EOF is encountered. So, the other side of Socket needs to close it - then the inStream.read() call will return.
Another method is to send the size of message you want to read first, so you know ahead how many bytes you have to read. Or you can use BufferedReader to read from socket in line-wise way. BufferedReader has a method readLine() which returns every time a line is read, which should work for you as HTTP protocol packages are nice divided into lines.
It will cycle until the connection is closed, and the client is probably waiting for HTTP response from you and doesn't close it.
The browser is waiting for a response before it closes the connection.
Your read-method on the other hand will block until the stream/connection is closed or new data is received.
Not a direct solution according to your current code.
As HTTP is a line based protocol, you might want to use a Buffered Reader and call readLine() on it.
The when a http request comes in it will always be concluded with a blank line, for example:
GET /someFile.html HTTP/1.1
Host: www.asdf.com
After sending that request the client connection will then wait for a response from the server before closing the connection. So if you want to parse the request from the user you are probably better off using a BufferedReader and reading full lines until you reach a lines of text that is blank line.

Categories

Resources