Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse an infinitley long input in Java

I wrote a "push server" that, when a client opens a connection, it remains open while the server writes to the stream. I would like to know how to write a client in Java that reacts to commands as it recieves them through this infinite lengthed response.

The problem is I have no idea where to start. If you could point me in the direction of a class where I could read the Javadoc, that would be great. I would like it to be able to respond instantly, so threads are probably a must.

Thank you so so much for any help!

Edit: By infinite length I mean unknown length. The word infinite was used to strenghten the point that the connection is usually never closed by the server. Not a whole lot of data is being transfered.

Another Edit: Maybe it would help to point out that this is an HTTP server running a PHP script.

like image 708
Osmium USA Avatar asked Dec 27 '12 17:12

Osmium USA


1 Answers

If they're simple commands separated by newlines, then it should be fairly simple to roll your own client:

EDIT: HTTP isn't the optimal protocol for keeping a long-lived connection open and you might run into timeout issues. The code below is untested but should give you a good starting point.

EDIT 2: As pointed out in the comments, the thread pool may or may not be necessary or useful here. You should note that using threads won't magically make things faster or increase the amount of requests you can handle. The benefit of using a thread pool is to allow the client to immediately receive new commands while a previous command is still executing. That might be important if processing the command requires some I/O task, e.g. calling out to another server, but in your situation it might be overkill.

ExecutorService svc = Executors.newCachedThreadPool();

URLConnection c = 
    new URL("http://192.168.1.122/push/out.php?nduid=1").openConnection();
c.setReadTimeout(30 * 60 * 1000); // Set the read timeout to 30 minutes
c.connect();
InputStream is = c.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));

String cmd = null;
while ((cmd = r.readLine()) != null) {
  svc.execute(new Runnable() {
    public void run() {
      processCmd(cmd); // work happens here in a different thread.
    }
  });
}

is.close();

The key here is that the input stream returned from the socket remains open as long as the underlying TCP connection remains open. The client can just keep reading from the stream, and the readLine call will simply block as necessary until new data arrives. When readLine returns null, that means the underlying input stream encountered end-of-file, which in turn means that the server closed the socket.

Once you have a full line of data, you can submit it to the thread pool to be parsed and executed in a different thread. Breaking the work up in this way allows you to focus on parsing and executing a command from a single line of text, which is much more manageable than trying to process an arbitrarily large stream of data.

like image 63
Alex Avatar answered Oct 07 '22 06:10

Alex