import java.io.*; import java.net.*; import java.util.*; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.*; import java.nio.charset.*; //----------------------------------------------------------------------- // Java NIO doesn't embrace stdin, so we have to resort to blocking IO // for stdin, which means we have to use a second thread for it. //----------------------------------------------------------------------- class InputWatcher extends Thread { Client client; InputWatcher(Client c) { client = c; } @Override public void run() { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String msg; try { while((msg = reader.readLine()) != null && msg.length() != 0) { client.processInput(msg); } } catch (IOException e) { // A Java programmer would know what to do here... } System.exit(0); } } //----------------------------------------------------------------------- // Here's the actual Client implementation //----------------------------------------------------------------------- public class Client { // socket related variables public DatagramChannel channel; public SocketAddress client_addr; class TimeoutTask extends TimerTask { Client client; TimeoutTask(Client c) { client = c; } @Override public void run() { client.fireTimeout(); } } TimerTask timeoutTask = null; Timer timer; private static final int SERVER_PORT = 33333; // constructor public Client(String hostname) throws IOException { channel = DatagramChannel.open(); InetSocketAddress serverAddress = new InetSocketAddress(hostname, SERVER_PORT); channel.connect(serverAddress); timer = new Timer(true); } // processPacket() -- read and process an incoming UDP packet private void processPacket() throws IOException { ByteBuffer req = ByteBuffer.allocate(1400); SocketAddress sa = channel.receive(req); // (length of packet is in req.position) req.flip(); System.out.println(new String(req.array())); if ( timeoutTask != null ) timeoutTask.cancel(); timeoutTask = null; } // processInput() -- process input read from stdin public void processInput(String msg) throws IOException { ByteBuffer buf = ByteBuffer.allocate(1400); buf.put(msg.getBytes()); buf.flip(); channel.write(buf); if ( timeoutTask == null ) { timeoutTask = new TimeoutTask(this); timer.schedule(timeoutTask, 5000); } }; // fireTimeout() public void fireTimeout() { System.out.println("No response"); timeoutTask = null; } //----------------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------------- static public void main(String[] args) { if ( args.length != 1 ) { System.err.println("Usage: java Client server_host"); System.exit(-1); } String serverHost = args[0]; Selector selector = null; Client client = null; try { client = new Client(serverHost); selector = Selector.open(); client.channel.configureBlocking(false); client.channel.register(selector, SelectionKey.OP_READ); } catch (IOException e) { System.err.println( "network error: " + (e.getMessage()!=null?e.getMessage():"")); // An error creating the client is fatal System.exit(1); } InputWatcher watcher = new InputWatcher(client); watcher.start(); while (true) { try { selector.select(); Iterator selectedKeys = selector.selectedKeys().iterator(); while (selectedKeys.hasNext()) { try { SelectionKey key = (SelectionKey) selectedKeys.next(); selectedKeys.remove(); if (!key.isValid()) continue; // something readable has arrived if (key.isReadable()) { client.processPacket(); } } catch (IOException e) { System.err.println("glitch, continuing... " +(e.getMessage()!=null?e.getMessage():"")); } } } catch (IOException e) { System.err.println("glitch, continuing... " +(e.getMessage()!=null?e.getMessage():"")); } } } }