tags:

views:

2172

answers:

4

I want to be able to asynchronously wait on socket, then synchronously read from it:

for (;;) 
{
    while (data available on socket) 
    {
        read message from socket;
        process it;
    }
    do something else;
}

(I need this because I want to poll a queue with messages from GUI at the same time, so the "do something else" part has a short wait().)

Is this possible with Java sockets? I tried to check .available() on a DataInputStream associated with the socket, but

  • it seems to work only when I connect, not when I accept a connection (???)
  • I get no indication that the connection has been closed.

I tried to do it with a Selector, but it requires the socket channel to be in non-blocking mode all the time.

A: 

In sockets programming the data may come in as arbitrary chunks depending upon the interaction between the sending system, intermediate links and how your OS treats PSH flags. You'll need to put a BufferedInputStream in the middle and make use of the available() method and push back bytes until you have a complete "message" which you can then process.

The correct java solution involves making your own MessageInputStream which wraps a BufferedInputStream and provides similar available() functionality which tells the caller how many messages are immediately available for reading.

caskey
+2  A: 

Why don't you use two threads (or am I misunderstanding what you want to do)?

objects
I wanted to avoid splitting this into two threads, but maybe it's the best way...
hmp
You can do what you suggest, but you would make it far more complicated than just using two threads.
Peter Lawrey
+2  A: 

The Java non-blocking I/O package (java.nio) will allow you to do asynchronous reading from a socket via Selectors.

Check this link for some examples to get you started.

Yuval A
A: 

I'd do

public class MainClass extends WhateverSuperClass implements WhateverInterface { 
// . . .

  private Listener listener;

  public MainClass() {
    listener = new Listener(this);
  }

  public void theMethod(){
    //do something else
  }
}

public class Listener extends Thread {
  public Listener(MainClass clazz) {

    // initialize thread resources (sockets, database connections, etc)
    start();
    Thread.yield();
  }

  public void run() {
    for (;;) 
    {
      // there's no need to test if there is 
      // data available on socket, since this
      // loop runs in a separate thread

      // read message from socket;
      // clazz.process(message);
    }
  }
}

Reginaldo