TCP socket: Why BufferedReader.readLine() get NULL? - java

I have a classic Java client/server app, where client and server exchange messages by a TCP connection.
When one elemement, let's call it Receiver (no matter if client or server), has to receive a message, it listens and waits for a message coming from the other element, let's call it Sender.
The receiver implements it by the following code:
BufferedReader myBufferedReader = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
receivedMessageCompleto = myBufferedReader.readLine();
The sender, after some time, will send a text message implementing the following code:
String messageCompleto = "whatever text";
String packetSend = messageCompleto + '\n' ;
DataOutputStream myDataOutputStream = new DataOutputStream(mySocket.getOutputStream());
myDataOutputStream.writeBytes(packetSend );
The probelm is:
in some cases "myBufferedReader.readLine()" get null value, but I'm quite sure that the sender didn't send a message NULL.
The question is: why?
According to my understanding the Receiver should remain blocked until it receives something (let's consider that timeout is set to infinite), then "myBufferedReader.readLine()" should return a value only when something arrives. The point is that I'm sure that the sender didn't send a null message.
Any idea???
Thank you very much in advance
Fausto

public String readLine()
throws IOException
Reads a line of text. A line is considered to be terminated by any one
of a line feed ('\n'), a carriage return ('\r'), or a carriage return
followed immediately by a linefeed.
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
Basically you get null if the underlying stream hits EOF.

As it says in the documentation for the readLine method:
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
So, in your case, end-of-stream has been reached. Probably, the remote end of the socket was closed.

Related

How do I check if a client's socket InputStream contains data?

I want to check if the InputStream buffer contains any data which it can read and output without having to initially call readLine() and waiting for data.
I have looked into available() but this didn't seem to work as it always output 0.
while (true)
{
fromServer = in.readLine(); //Causing a hang waiting for reply
System.out.println(fromServer);
if ((fromUser = stdIn.readLine()) != null)
{
out.println(fromUser);
fromServer = in.readLine();
System.out.println(fromServer);
}
}
available() might tell you the number of bytes available, if implemented, but nothing can tell you whether there is a complete line other than trying to read it.
You need to read in a separate thread.
The issue is readLine() causes the client to get stuck hanging for a server reply if access isn't permitted for the client.
So the issue is really that the server should send something 'if access isn't permitted for the client', i.e. a message that says so, rather than doing nothing. You can't use absence of a message as a message in a blocking I/O system.
You also need to check every readLine() result for null, and if you get it when reading a socket you need to close it.
Create a new Instance of BufferedInputStream and call available on that object:
InputStream is = ...;
BufferedInputStream bis = new BufferedInputStream(inputStream);
if (bis.available() == 0) {
// do sth if input is available
}
I tried it with a little server-client application, it worked for me.
EDIT: Type mismatch gone.
As the Java Documentation says, the InputStream.available() always returns zero. In comparison to that, the BufferedInputStream returns „the number of bytes remaining that can be read in the buffer“

client cant read from server with readLine

I have a made a socket connection between client and server. Everything is working good if i introduce the first comand on client, receiving the message i want from the server.
#server
public PrintWriter out;
out.println(res);
#client
public BufferedReader in = null;
String line;
line = in.readLine();
At the second time i run it won't show the message i send from server cause it will read \n so it will be an empty string. If i change this:
#server
out.println("\n"+res);
The first time i run now it will jump a line, printing just the \n. And the second time i run it will show the right message.
If i change now to:
out.println("\n\n"+res);
It will just show when i introduce something to send to the server and receive back after the 3rd time (the first 2 times it prints \n).
Don't know what to do to show always the message i send from the server. Any advice?

PrintWriter only sending string with println and not print

I am building a client/server application and I am trying to send a String to the client from a server thread using a PrintWriter. I construct my PrintWriter like this:
// Instantiate a PrintWriterwith a correctly implemented
// client socket parameter, and autoflush set to true
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
Assume, further, that the client is reading from the input stream with a BufferedReader, that is instantiated as such:
BufferedReader in = new BufferedReader(new InputStreamReader(client.server.getInputStream()));
and the client gets messages from the server with:
String serverMessage = in.readLine();
As you can see, I've set autoflushing to true. Let's say, now, that I want to send a simple message to a client. If I execute the statement:
out.println("Message to client");
Then the message is successfully sent. However, if I execute the statement:
out.print("Message to client");
then the message is not sent. Also:
out.print("Message to client");
out.flush();
does not work either.
This is a problem because I need to send a message to a client in a terminal and have them be able to respond on the same line. How do I send a message, using a PrintWriter, so that it gets flushed/sent to the client, but it does not send a newline character?
In your case it seems like you are using BufferedReader#readLine() which will read characters until a newline character or the end of stream is reached, blocking in the meantime. As such, you'll need your server to write that new line character.
An alternative is to read bytes directly instead of relying on BufferedReader#readLine().
why doesn't using a carriage return work?
The newline character is system-dependent. On Windows it is \r\n. On linux it is \n. You can get that with
System.getProperty("line.separator")
but you will need to get the server's.

Socket readline not blocking

Events are being forwarded to a client socket, which is being read by the code below. Most of the time the code works as expected. Sometimes a data packet is sent to the socket which causes the readline to unblock with a null message. From that point forward, the readline call never blocks again, causing a CPU spike. I have verified with code that the socket is not closed, the input stream has not been shutdown, isSocketClosed and isInputShutdown both return false. The ready call is just an attempt to see what's happening, the read call always returns -1. The socket is still accepting data, new valid packets come in, processed correctly, but the readline never blocks again. Any idea how why readline is behaving this way?
while (!this.isInterrupted())
{
String message = null;
do {
message = reader.readLine();
if ( message != null && message.length() > 0 ) {
//if ( log().isDebugEnabled())
log().info( "Got a message, raw data: " + message );
createEvent( message );
}
} while ( message != null && !this.isInterrupted());
if(!reader.ready()) {
log().info("Bytes read: " + reader.read());
Thread.sleep(1000);
}
}
BufferedReader.readLine() returns null when the other end closes the connection.
If it is not doing this you have a particularly bug JVM. I would make sure you have the latest update.
I have verified with code that the socket is not closed, the input stream has not been shutdown, isSocketClosed and isInputShutdown both return false
This just means your end didn't close() the stream. It doesn't tell you anything about the other end of the stream.
The ready call is just an attempt to see what's happening, the read call always returns -1
This also means you have an end of stream.
Just a small thing, but if you have empty (not null) strings coming in on your socket, they won't fall under if ( message != null && message.length() > 0 ).
You might wanna change it to if ( message != null ).
The reason this happens comes from the String#length() method:
Returns the length of this string. The length is equal to the number
of Unicode code units in the string. #return the length of the
sequence of characters represented by this object.
You have a bug in your code. If readLine() returns null, it means the peer has closed the connection. You must do likewise and exit the loop. Once it has returned null, it will never block again, and it will never stop returning null.
The part of your loop that tests ready() and sleeps is literally a compete waste of time. Remove it.

Java if/else behaving strangely

I'm a real newbie to java, so please excuse me if this is a hopelessly straightforward problem.
I have the following from my java game server:
// Get input from the client
DataInputStream in = new DataInputStream (server.getInputStream());
PrintStream out = new PrintStream(server.getOutputStream());
disconnect=false;
while((line = in.readLine().trim()) != null && !line.equals(".") && !line.equals("") && !disconnect) {
System.out.println("Received "+line);
if(line.equals("h")){
out.println("h"+EOF); // Client handshake
System.out.println("Matched 1");
}else if (line.equals("<policy-file-request/>")) {
out.println("..."+EOF); // Policy file
System.out.println(server.getInetAddress()+": Policy Request");
disconnect=true;
System.out.println("Matched 2");
}else if(line.substring(0,3).equals("GET")||line.substring(0,4).equals("POST")){
out.println("HTTP/1.0 200 OK\nServer: VirtuaRoom v0.9\nContent-Type: text/html\n\n..."); // HTML status page
disconnect=true;
System.out.println("Matched 3");
} else {
System.out.println(server.getInetAddress()+": Unknown command, client disconnected.");
disconnect=true;
System.out.println("Matched else");
}
}
server.close();
First of all, the client sends an "h" packet, and expects the same back (handshake). However, I want it to disconnect the client when an unrecognised packet is received. For some reason, it responds fine to the handshake and HTML status request, but the else clause is never executed when there's an unknown packet.
Thanks
From the information added in your comments it seems that what will be happening is the client is sending a single character (e.g. 'n'). The line
line.substring(0,3).equals("GET")||line.substring(0,4).equals("POST"))
will be executed, but since line is only a single character line.substring(0,3) will throw a StringIndexOutOfBoundsException. Either this is causing your program to fail and you haven't mentioned that. Or you have some exception handling going on in another part of your code that you haven't shown and this is either supressing the error or printing a log line or something and again you haven't mentioned this (or noticed it).
Try replacing substring().equals with startsWith
You need to check for null before you trim it. The result of trim() can never be null.
You should check disconnect first, before the readLine(), otherwise you are always doing one readLine() too many.
If you are never getting to your 'else' it means one of the other conditions is always true.
There are a number of problems with your code
in.readLine().trim()
readLine do returns null and calling null.trim() will result in ... NullPointerException
Is there a reason to append EOF to every response you send.
calling substring without making sure it has at least that much elements will throw StringIndexOutOfBoundsException if it is shorter.
Are you testing with "P" for example?
It would seem highly unlikely that the else is not executing. Are you sure your loop does not exit on such packets and hence your conditions do not even run? Does your
System.out.println("Received "+line); print anything for the packet that seems to be missing the else statement?

Categories