1

Saying my requirement is: Either user type something in console (from system.in) or socket receive something, proceed to next step.

So I have a scanner

Scanner sc = new Scanner(System.in);

Have an Udp client. (a different input source)

DatagramSocket clientSocket = new DatagramSocket();

My code is

while (true) {
     if (sc.hasNext()) {
        String str = sc.next();
        proceed(str)
     } else { 
        clientSocket.receive(pack);
        proceed(pack)
     }
}

Obviously this code will not work. Because when checking sc.hasNext(), java is waiting user to type some input in console. Currently what I can do is open an thread for Udp client. If I change the order,

while (true) {
         clientSocket.receive(pack);
         if (not receive)  read from system.in
    }

It doesn't make sense, since receive() will keep waiting util receive something, it will never read from system.in concurrently.

So how can i achieve my requirement without using a thread?

Inspired by @Andriy Kryvtsun's answer, i did a quick test As he said, this is somehow using non-blocking read, and keep letting socket timeout, to emulate

        InputStream ins = System.in;
    byte buffer[] = new byte[512];
    BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
    DatagramSocket clientSocket = new DatagramSocket();
    System.out.println("From buffer:" + clientSocket.getLocalPort());

    while (true) {
        try {
            if (ins.available() > 0) {
                String line = reader.readLine();
                System.out.println("Read:" + line);
            } else {

                DatagramPacket pack = new DatagramPacket(buffer,buffer.length);
                clientSocket.setSoTimeout(2000);
                clientSocket.receive(pack);
                System.out.println("Receive: " + new String(pack.getData()));
            }
        } catch (IOException e1) {

        }
    }
TTTTTAAOOOO
  • 43
  • 1
  • 6
  • 1
    System.in is a blocking stream so there is no limit to how long it might block for. You need to use a thread (or two) for the Socket handling. – Peter Lawrey Mar 24 '16 at 17:13
  • Sounds like you might want to use something from the `java.nio.channels` package, but I don't know what exactly because I've never used it myself. I would use threads to solve the problem that you describe. – Solomon Slow Mar 24 '16 at 17:41
  • yes. I also found those non-blocking things. As the requriement is not to use thread. I have to find a non-blocking way. – TTTTTAAOOOO Mar 24 '16 at 18:20

1 Answers1

2

Use unblocking method call InputStream#available() to get info if something ready for reading before using blocking Scanner#hasNext() call.

Also you can call DatagramSocket#setSoTimeout(int timeout) before call blocking receive(DatagramPacket p) method. Thus you can break infinity waiting inside receive method after timeout period emulating unblocking reading.

Andriy Kryvtsun
  • 3,220
  • 3
  • 27
  • 41
  • Thanks Andriy, this is helpful. I have put my code here. The only thing is, if i set timeout as 2 seconds, when i type something in console, i have to wait around 1 seconds to get it printed out. Because it's waiting for timeout. I think this is something we can't avoid. Please correct me if i am wrong. – TTTTTAAOOOO Mar 24 '16 at 19:09