Setting a time-out limit to readLine()? - java

I have the following code that reads response from a POP server through Sockets in Java. But the problem is sometimes, when I use the readLine() function to read from the server and if the server does not reply with any response, my application will hang there, waiting for a response from the server.
socket.connect(new InetSocketAddress("pop.server.com", 110), 3000);
input = socket.getInputStream();
BufferedReader incoming = new BufferedReader(new InputStreamReader(input));
incoming.readLine(); //This line will cause my application to hang if the server does not respond with a reply
Is there a way to set a timeout or some other ways that when the server does not reply after a certain amount of time, the application should stop waiting for a response and continue its other execution?

I suggest you try Socket.setSoTime(timeout)

Related

TCP java chat, client not listen

I have problem with my ClientListener, server send TCP package but Client do not display it.
Here is my code
https://github.com/Behoston/sieci/tree/master/src/tcp
(Server run new thread for each new client and this thread (to listen) and this thread run other to sending messages (it works - I can see messages in wireshark
Client run main thread where can input some text and second therad (not working properly) to listen messages from serever)
It's quite hard to answer your question if you only provide a link to your repository, some code snippets of the crucial classes or methods would be helpful.
If my understanding of the classes you provided is correct, this is the workflow you are trying to implement (correct me if I'm wrong):
Server gets started
Client connects
Server sends a welcome message (which is not getting displayed on clientside):
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes("Hello, your ID is: " + clientId + "; To send message please use 3 first chars to set target");
On the recieving side:
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
response = inFromServer.readLine();
As far as I see, you are waiting for a readLine() with your server sending a byteArray. Since readLine() waits for a line seperator (f.e. "\n"), your messages can't be processed.

Server receiving packets after timeout TCP/IP

I am writing simple Server through TCP/IP for my android app.
I am facing a problem where server only receives messages after the timeout on the app.
My server side:
System.out.println("Connection accepted");
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
capitalizedSentence = "READY";
writeToUser(outToClient, "READY".getBytes());
String response = readFromUser(connectionSocket);
// Server hangs on readFromUser();
if(response.contains("IL"))
{
byte[] bytes = DatatypeConverter.parseHexBinary(foo);
writeToUser(outToClient, bytes);
}
App side:
if (ack.equals("READY")) {
ack = "";
dataOutputStream.writeBytes(command);
dataOutputStream.flush();
buf = new byte[556];
dataInputStream.read(buf);
// app hangs on read() and gets timeout
}
The problem is that, server receives command only after application gets read timeout.
My current scenario is this:
Connection accepted: Application receives "READY"
Application sends commands and tries to read response from server
Server is hanging on readFromUser() and only receives message after the app gets read timeout.
Any ideas what am I doing wrong ?
Update:
The code works if I use readLine, instead of read(buf) ( if I understand clearly server hangs on read(buf) and is in waiting mode as socket is not closed yet even though no more data is beeing sent. )
However such way I have to add "\n" after each command, and server is only emulator, app works with different device who does not understand "\n" at the end and will crash.
Is there any way I could make this work without using readLine() ?
Update 2
public void writeToUser(DataOutputStream outToClient, byte[] bytes) throws IOException
{
outToClient.write(bytes);
outToClient.flush();
String s = new String(bytes);
writeLog("Sent to client: " + s);
}
public String readFromUser(Socket socket) throws IOException, InterruptedException
{
writeLog("Reading...");
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String clientSentence = inFromClient.readLine();
writeLog("Received: " + clientSentence);
return clientSentence;
}
Above readFromUser() method works just as expected. But, this requires adding "\n" on each command sent from client app. And real device I have to communicate with does not understand "\n" and will treat the command as unrecognized... I am writing this server simply for testing purposes and I want it to be as close to real one as possible.
Previously I was just trying to get it done without "\n" on each command using inFromClient.read(cbuf); instead of readLine() and server always got hung on read, and received command only after socket was closed on client side. Even though I know that client sent the command and is waiting for response.
The question is how can I receive command without using readLine(); and "\n" on client side.
'how can I receive command without using readLine(); and "\n" on client side'. If you do not, or can not, want to use "\n" as a command terminator, then you must use another protocol to identify the start and end of the 'command' within the TCP octet/byte stream.
What protocol does your 'real device' server use to identify the start and end of commands? If it uses a byte-by-byte state-machine to identify a valid command then you are going to have to duplicate that in your test server.
You're reading lines but you aren't writing lines. So readLine() blocks until a line terminator arrives or the peer closes the connection.
Append a \n.
Why not you increase timeout from APPs side. Or you can write a thread that will hit server in some interval for some time and if no response then show time out. This problem is in Apps side.

BufferedReader.lines().foreach() never terminates

I'm trying to read a HTTP request from a Bufferedreader, that gets Socket.getInputStream() as input. However, when I use Bufferedreader.lines().foreach(), it never terminates and it just gets stuck.
My code (simplified):
Socket socket = new ServerSocket(9090);
Socket newConnection = socket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(newConnection.getInputStream()));
reader.lines().forEach(s -> System.out.println(s));
You need to read more about the HTTP 1.1 protocol. Requests aren't terminated by end of stream. They are terminated by exhausting the byte count in the Content-length header, or of the cumulative chunks if chunked transfer mode is in use. If they were exhausted by end of stream, you could never send a response.
Try creating your socket with parameter-less constructor and use connect() method with port and timeout parameter. This will prevent endless freeze.

Does a Socket InputStream read() unblock if server times out?

I have a server that times out after 45 seconds if it hasn't received a full request and closes the connection. I connect to this server through a Socket and write my request to the socket's OutputStream.
Socket socket = new Socket("myhost", myPort);
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.write(properRequestMessage);
out.flush();
I'm assuming here that my request is good (follows my protocol). The server is supposed to respond with a file. I try to read from the socket inputstream:
BufferedReader response = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String in;
while((in = response.readLine()) != null) {
System.out.println(in);
}
The readLine() blocks here and I think it is because my server thinks my request isn't properly terminated and is therefore waiting for more.
Now, if 45 seconds pass and my server times out, will the readLine() unblock or wait for some Socket default timeout time?
That depends on what the server does when it times out. If it closes the connection you will see that. If it just logs a message, you might not see anything.
There is no default read timeout. Your readLine() can wait forever.
If the server closes its end of the socket on that timeout, then readLine() will return null.
The readLine() method will block until it receives an input or until the underlying socket read() timeout ends.
You don't set the timeout on the read command but rather on the socket it self.
Socket.setSoTimeout(int ms).
Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.
What actually occurs also depends on what the server does, if it closes the socket correctly a IOException should be thrown by readLine(). If the connection isn't close it will wait for the socket to timeout.

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