0

I am trying to create a java http server using tcp sockets. HTTP 1.1 has a timeout value that will enable the connection to be persistent and wait for a short while for possible data from the client. I am trying to implement this timer in my program by using:clientSocket.setSoTimeout(). Even though this will help to leave the connection open for a certain amount of time, but it will wait for that exact amount of time before allowing the next request to be read.

For example:

If timeout is set to 5 seconds,

Request 1 is read. Then the socket hangs and wait until 5 seconds is over.
Request 2 is read. The socket waits until 5 seconds is up again.

This proves to be a problem if my timeout is set to big values. This should not be the case as the request should be processed once it is received and the timeout should only expire only if no data is received throughout the specified duration.

Can anyone advise me on how I could resolve this?

Edit:

For people who face a similar problem, here is my solution:

Since the client waits until the timeout before receiving all the data, I guessed that the client does not know that all the data from the server has been received. Hence, I added a content-length field to the HTTP response packet. Now, my client no longer hangs after receiving the data. The setSoTimeout does indeed work as stated!

Donald
  • 1,300
  • 2
  • 13
  • 29
  • Can you show some of your code? Maybe the part accepting clients? – Beethoven Sep 09 '16 at 06:14
  • I only used one line to accept clients: `client = server.accept();` It is put in a `while(true)` loop to continuously listen for connections. – Donald Sep 09 '16 at 06:16
  • Sure, but what happens then? I suspect, that you miss passing the task of processing a client to another thread, but it is difficult to tell where the exact problem lies without seeing any code. That's why they talk about a "Minimal, Complete, and Verifiable example" in the help center. http://stackoverflow.com/help/mcve – Beethoven Sep 09 '16 at 06:21
  • My server is not using any multithreading. Is it possible to do the timeout without multithreading? – Donald Sep 09 '16 at 06:22
  • No, it is not. If you want to process multiple clients concurrently, you will have to use multiple concurrently running threads. – Beethoven Sep 09 '16 at 06:23
  • My server only needs to handle one client – Donald Sep 09 '16 at 06:24
  • Apparently it does need to handle multiple clients, if the server needs to stay responsive while the connection to another client is hanging. Or am I completely misunderstanding something? – Beethoven Sep 09 '16 at 06:27
  • Let's assume that I only need to handle requests from one client and respond to it. How would I implement the timeout in this case? E.g. I am testing it using wget to download objects from it. – Donald Sep 09 '16 at 06:28
  • You will need a multithreaded server, when you have more than one (possibly hanging) connection open, even if you only respond to one client at a time. – Beethoven Sep 09 '16 at 06:32
  • I am not using pipelining in my server. I am only trying to implement persistent connection. This would mean that my server will send HTTP responses over the same TCP connection. So there will only be one connection at any one time – Donald Sep 09 '16 at 06:35
  • What happens if you don't call `setSoTimeout`? The connection should stay open until you call `client.close()`. – Beethoven Sep 09 '16 at 06:43
  • Yes. That is correct. But I want to close the socket after a certain amount of idle time. That is what HTTP 1.1 does right? – Donald Sep 09 '16 at 06:55
  • 1
    'Persistent connection' does not mean 'the server will send the response over the same connnection'. That is always the case in HTTP. It means the client can send more requests over the same connection. And HTTP doesn't 'do' anything. Implementations do it. You're implementing it: you do it. You need a much better knowledge of HTTP than you presently have to get anywhere with this project. – user207421 Sep 09 '16 at 07:09
  • You are barking up the wrong rabbit-hole here. I suggest you cut out the guesswork, delete this question, and post your *real* problem. I am going to speculate that you haven't implemented Content-length or chunked transfer encoding, and that *this* is the real source of your problem. You need a good knowledge of RFC 2616 and successors to implement HTTP 1.1, and so far you haven't deomonstrated any – user207421 Sep 09 '16 at 09:00
  • Re your edit, it is exactly as I said over five weeks ago. You hadn't implemented `Content-length` or chunked transfer-encoding. – user207421 Oct 17 '16 at 05:49
  • @EJP Yes. I didn't manage to understand what you meant then. But after analysing the various possibilities and solving the problem, I finally do. – Donald Oct 17 '16 at 05:54

2 Answers2

0

Ok, when you receive a connection, then please start a new Thread like this:

class ClientService extends Thread {

    private final Socket clientSocket;

    public ClientService(Socket clientSocket) {
      this.clientSocket=clientSocket;
    }

    public void run() {
      // do your work with the Socket clientSocket here
    }

}

this is how then your server code should look like:

while (true) {
    Socket clientSocket = server.accept();
    new ClientService(clientSocket).start();
}

It will allow you to process responses without waiting for one another till it timeouts.

Krzysztof Cichocki
  • 6,294
  • 1
  • 16
  • 32
  • I am handling one client with single persistent connection only. So there should be no need for multithreading right? – Donald Sep 09 '16 at 06:51
  • simple answer: nope. Even with single client your connection can hang till it timeout, and if you want the client to be able to make another one without waiting for previous connection to finish then you need multithreading. There's plenty of situations in which client could disconnect and try to reconnect immediately, without multithreading it will need to wait till previous "dead" connection will timeout and let another one be processed. – Krzysztof Cichocki Sep 09 '16 at 07:00
  • If I use setSoTimeout(), will the socket stop waiting immediately after it receives data? – Donald Sep 09 '16 at 07:38
  • @LanceHAOH Of course it will. It's a timeout. Arrival of data within the timeout => there is no timeout. – user207421 Sep 09 '16 at 08:57
0

HTTP 1.1 has a timeout value that will enable the connection to be persistent and wait for a short while for possible data from the client.

Not really. It has a connection: keep-alive setting, which is the default behaviour, and it allows endpoints to close connections that aren't in use after a period of idleness, but it doesn't have a timeout property itself.

I am trying to implement this timer in my program by using:clientSocket.setSoTimeout().

This has nothing whatsoever to do with HTTP. It is a socket read timeout.

Even though this will help to leave the connection open for a certain amount of time, but it will wait for that exact amount of time before allowing the next request to be read.

No it won't. It will cause read methods to throw SocketTimeoutException if no data arrives within the timeout period. Nothing else.

For example:

If timeout is set to 5 seconds,

Request 1 is read. Then the socket hangs and wait until 5 seconds is over.

No it doesn't.

Request 2 is read. The socket waits until 5 seconds is up again.

No it doesn't. You've made all this up. It is fantasy.

This proves to be a problem if my timeout is set to big values.

It isn't a problem with any timeout values whether large or small, because it simply does not happen.

This should not be the case as the request should be processed once it is received and the timeout should only expire only if no data is received throughout the specified duration.

That is exactly what Socket.setSoTimeout() already does.

Your question is founded on a fallacy.

Community
  • 1
  • 1
user207421
  • 305,947
  • 44
  • 307
  • 483
  • If I set the timeout to be a large value, I observed that there is a long lag before the next request is sent. – Donald Sep 09 '16 at 07:14
  • The socket throws timeout exception after every request is read. Then the client has to make a new connection just to download the next file. Isn't this enough to prove my point? – Donald Sep 09 '16 at 07:31
  • The socket throws a timeout exception *while you are reading the next request*. Not 'after every request is read'. The socket didn't just spontaneously 'hang until the 5 seconds was over'. The lag before the next request means that the client didn't send one within the timeout period, so you got a read timeout, so you got a `SocketTimeoutException`, exactly as I have said above. So what you have just implemented, correctly, is a server-side connection idle timeout. I don't know what point of yours this is supposed to prove, but it doesn't, or what your question consists of, if anything. – user207421 Sep 09 '16 at 08:20
  • How can this explain the fact when I increase the timeout to 20 sec, then there is more lag in the response time? E.g. my browser takes very long to load the web page and objects in this case. – Donald Sep 09 '16 at 09:39
  • 1
    @LanceHAOH It is completely and utterly pointless to try to discuss the behaviour of your code without you having posted the code. – user207421 Sep 09 '16 at 09:57