NIO example

I am trying to learn NIO, and am looking for a good example that shows how to create a server that handles multiple clients that REMAIN connected, and pass potentially multiple commands...
Any links/sample code?
Thanks.

Take a look at the topic Taming the NIO Circus. It starts with a simple multi-socket echo server and a swing client. The echo server has multiple sockets that remain connected until closed by their clients. It them goes on for over 100 replies to discuss most of the pitfalls you will encounter using NIO. Another really good resource is Ron Hitchen's Java NIO published by O'Reilly.

Similar Messages

  • New I/O (NIO)

    i am trying to understand how to use NIO for a server/chat program
    I have seen many examples online but they are all very complex
    does anyone know of or have any simple examples?
    Thank you in advance
    Anchal Nigam

    Here are some examples which might not be too complex.
    http://java.sun.com/j2se/1.4.2/docs/guide/nio/example/
    Kaj

  • Selecting between java.io and java.nio

    Hi,
    I'm a bit confused between java.io and java.nio. What sre the major differences between these two?
    In areas are these best applicable?

    The java.nio package improves on the basic Java I/O that was available prior to JDK 1.4.
    It is designed to interoperate more natively with the underlying file handles (sockets, open files etc) to achieve better performance.
    The improvements include true non-blocking I/O, better buffer management, character-set support, channels (similar to Occam's channels) and selectors, and some other ancillery stuff. Most of these classes are designed to be inherently threadsafe.
    There are some examples here:
    http://java.sun.com/j2se/1.4.2/docs/guide/nio/example/index.html
    However, if you are still a beginner with file or network I/O, its better if you start with the simple I/O first. You'll appreciate the NIO improvements better afterwards.

  • Error SocketChannel receive multiple messages at once?

    Hello,
    I use Java NIO, non blocking for my client-server program.
    Everything works ok, until there are many clients that sending messages at the same time to the server.
    The server can identify all the clients, and begin reading, but the reading of those multiple clients are always the same message.
    For example, client A send "Message A", client B send "Missing Message", client C send "Another Missing Message" at the same time to the server, the server read client A send "Message A", client B send "Message A", client C send "Message A", only happen if the server trying to read all those messages at once, if the server read one by one, it's working perfectly.
    What's wrong with my code?
    This is on the server, reading the message:
    private Selector               packetReader; // the selector to read client message
    public void update(long elapsedTime) throws IOException {
      if (packetReader.selectNow() > 0) {
        // message received
        Iterator packetIterator = packetReader.selectedKeys().iterator();
        while (packetIterator.hasNext()) {
          SelectionKey key = (SelectionKey) packetIterator.next();
          packetIterator.remove();
          // there is client sending message, looping until all clients message
          // fully read
          // construct packet
          TCPClient client = (TCPClient) key.attachment();
          try {
            client.read(); // IN HERE ALL THE CLIENTS READ THE SAME MESSAGES
               // if only one client send message, it's working, if there are multiple selector key, the message screwed
          } catch (IOException ex) {
    //      ex.printStackTrace();
            removeClient(client); // something not right, kick this client
    }On the client, I think this is the culprit :
    private ByteBuffer            readBuffer; // the byte buffer
    private SocketChannel  client; // the client SocketChannel
    protected synchronized void read() throws IOException {
      readBuffer.clear();    // clear previous buffer
      int bytesRead = client.read(readBuffer);  // THIS ONE READ THE SAME MESSAGES, I think this is the culprit
      if (bytesRead < 0) {
        throw new IOException("Reached end of stream");
      } else if (bytesRead == 0) {
        return;
      // write to storage (DataInputStream input field storage)
      storage.write(readBuffer.array(), 0, bytesRead);
      // in here the construction of the buffer to real message
    }How could the next client read not from the beginning of the received message but to its actual message (client.read(readBuffer)), i'm thinking to use SocketChannel.read(ByteBuffer[] dsts, , int offset, int length) but don't know the offset, the length, and what's that for :(
    Anyone networking gurus, please help...
    Thank you very much.

    Hello ejp, thanks for the reply.
    (1) You can't assume that each read delivers an entire message.Yep I know about this, like I'm saying everything is okay when all the clients send the message not in the same time, but when the server tries to read client message at the same time, for example there are 3 clients message arrive at the same time and the server tries to read it, the server construct all the message exactly like the first message arrived.
    This is the actual construction of the message, read the length of the packet first, then construct the message into DataInputStream, and read the message from it:
    // packet stream reader
    private DataInputStream input;
    private NewPipedOutputStream storage;
    private boolean     waitingForLength = true;
    private int length;     
    protected synchronized void read() throws IOException {
      readBuffer.clear(); // clear previous byte buffer
      int bytesRead = client.read(readBuffer); // read how many bytes read
      if (bytesRead < 0) {
        throw new IOException("Reached end of stream");
      } else if (bytesRead == 0) {
        return;
      // the bytes read is used to fill the byte buffer
      storage.write(readBuffer.array(), 0, bytesRead);
      // after read the packet
      // this is the message construction
      // write to byte buffer to input storage
      // (this will write into DataInputStream)
      storage.write(readBuffer.array(), 0, bytesRead);
      // unpack the packet
      while (input.available() > 0) {
        // unpack the byte length first
        if (waitingForLength) { // read the packet length first
          if (input.available() > 2) {
            length = input.readShort();
            waitingForLength = false;
          } else {
            // the length has not fully read
            break; // wait until the next read
        // construct the packet if the length already known
        } else {
          if (input.available() >= length) {
            // store the content to data
            byte[] data = new byte[length];
            input.readFully(data);
            // add to received packet
            addReceivedPacket(data);
         waitingForLength = true; // wait for another packet
          } else {
            // the content has not fully read
         break; // wait until next read
    (2) You're sharing the same ByteBuffer between all your clients
    so you're running some considerable risks if (1) doesn't happen.
    I recommend you run a ByteBuffer per client and have a good look
    at its API and the NIO examples.Yep, I already use one ByteBuffer per client, it's not shared among the clients, this is the class for each client:
    private SocketChannel client; // socket channel per client
    private ByteBuffer readBuffer; // byte buffer per client
    private Selector packetReader; // the selector that is shared among all clients
    private static final int BUFFER_SIZE = 10240; // default huge buffer size for reading
    private void init() throws IOException {
      storage; // the packet storage writer
      input; // the actual packet input
      readBuffer = ByteBuffer.allocate(BUFFER_SIZE); // the byte buffer is one per client
      readBuffer.order(ByteOrder.BIG_ENDIAN);
      client.configureBlocking(false);
      client.socket().setTcpNoDelay(true);
      // register packet reader
      // one packetReader used by all clients
      client.register(packetReader, SelectionKey.OP_READ, this);
    }Cos the ByteBuffer is not shared, I think it's impossible that it mixed up with other clients, what I think is the SocketChannel client.read(ByteBuffer) that fill the byte buffer with the same packet?
    So you're probably getting the data all mixed up - you'll probalby be seeing a new client message followed by whatever was there from the last time, or the time before.If the server not trying to read all the messages at the same time, it works fine, I think that if the client SocketChannel filled up with multiple client messages, the SocketChannel.read(...) only read the first client message.
    Or am I doing something wrong, I could fasten the server read by removing the Thread.sleep(100); but I think that's not the good solution, since in NIO there should be time where the server need to read client multiple messages at once.
    Any other thoughts?
    Thanks again.

  • How to check if remote host is alive

    Hi,
    i was wondering how you could implement a ICMP ping message in java so that a low priority thread can be written so as to ping remote host to verify if the host is still alive?
    any links or help would be greatly appreciated. pls allow me to thank all of you in advance
    rgds,
    Javier

    There is a sample for new nio packages at:
    http://java.sun.com/j2se/1.4/docs/guide/nio/example/index.html
    Please, see Ping.java

  • NIO with SSLEngine API - Simple example required

    Hi
    I am trying to implement a NIO Server with SSL Engine based implementation. I went through the Https server given in the samples provided with jdk 5.0. But that is little bit more complicated (uses Handlers and other associated functionality). what I am looking for is a simple example program which can elucidate the SSL Engine API operations and the bare minium code to execute a simple Client Server communication through SSL Engine. I know it has a long learning curve, just thought if somebody has researched well and posted an article/tutorial in this regard, it would be really helpful for novice programmers like me. Please help with some sample programs..
    Thanks

    Unfortunately the bare minimum is extremely complicated. The JSSE samples contain some simplistic NIO code but it barely works, and doesn't cope with useClientMode=true at the server, or with re-handshakes.
    There is some PD code out there if you can find it, and also several discussions in the Secure Sockets forum.
    There is also an entire chapter on it in my book http://www.telekinesis.com.au/wipv3_6/FundamentalNetworkingInJava.A21.

  • Need an example of how to use java.nio.channels.FileLock

    Hi,
    I need to use the Filelock, but can�t find any examples on how to implement it -
    is it still used in Java 5.0?

    Would this be the correct way to check whether the file is already locked?
    public static void main(String[] args) throws Exception {
         FileOutputStream fos = new FileOutputStream("data.txt");
         FileLock fl = fos.getChannel().tryLock();
         if (fl != null) {
         System.out.println("Locked File");
         Thread.sleep(30000);
         fl.release();
         System.out.println("Released Lock");
         else{
              System.out.println("File is already locked!");
         fos.close();
         }

  • Socket example using Java 5

    Last year I posted 4 programs that provided a simple client server using both stream sockets and NIO. I decided as an exercise in using Java 5 to port that code and try to use as many of the new features as possible. The following code is very long and does what all the previous example programs did. In replies do not repost the whole of this message.
    It provides a simple chat like client and server. The user can request either a stream connection or a NIO connection or provide one of their own.
    //========================== MsgSwitch.java ===========================//
    package pkwnet.msgswitch;
    import java.util.logging.Logger;
    import java.util.logging.Level;
    import java.util.logging.Handler;
    * main class for message switch
    * command line arguments are
    * -p port number for server
    * -s run server
    * -a server ip address including port for client
    * -i idle timer in seconds
    * -n use NIO
    * -c specify connection class
    public class MsgSwitch {
        static private int errors = 0;
        static private String address = "127.0.0.1:6060";
        static private String connectionClass = "pkwnet.msgswitch.StreamConnection";
        static public void main(String [] args) {
            int port = 6060;
            int idleTime = 600;
            boolean server = false;
            boolean nio = false;
            Logger logger = Logger.getLogger("msgswitch");
            for(String arg : args) {
                if(arg.startsWith("-a")) {
                    address = arg.substring(2);
                } else if(arg.startsWith("-p")) {
                    port = argToInt(arg);
                    server = true;
                } else if(arg.startsWith("-i")) {
                    idleTime = argToInt(arg);
                } else if (arg.startsWith("-s")) {
                    server = true;
                } else if (arg.startsWith("-c")) {
                    connectionClass = arg.substring(2);
                } else if (arg.startsWith("-n")) {
                    connectionClass = "pkwnet.msgswitch.NIOConnection";
                } else {
                    String err = "unknown argument=" + arg;
                    logger.severe(err);
                    System.err.println(err);
                    errors++;
            if (errors == 0) {
                if (server) {
                    new Server().listen(port,idleTime, nio);
                } else {
                    new Client().start(address, nio);
            } else {
                fail(errors + " errors encountered", null);
        static private int argToInt(String arg) {
            int val = 0;
            try {
                val = Integer.parseInt(arg.substring(2));
            } catch (NumberFormatException e) {
                String err = "invalid argument format: " + arg;
                Logger.getLogger("msgswitch").severe(err);
                System.err.println(err);
                errors++;
            return val;
        static public void fail(String err, Throwable e) {
            String msg = "Operation terminated: " + err;
            Logger.getLogger("msgswitch").log(Level.SEVERE, msg, e);
            System.err.println(msg);
            System.exit(12);
        static public Connection getConnection() {
            Connection conn = null;
            try {
                conn = (Connection) Class.forName(connectionClass).newInstance();
            } catch (Exception e) {
                fail ("connection class error", e);
            return conn;
        static public void logCaller(Logger logger, Level level) {
            String text = "CALLED";
            if (logger.isLoggable(level)) {
                try {
                    throw new Exception("logging stack");
                } catch (Exception e) {
                    StackTraceElement [] st = e.getStackTrace();
                    if (st.length > 1) {
                        text += formatElement(st[1]);
                    if (st.length >2) {
                        text += formatElement(st[2]);
                logger.log(level, text);
        static private String formatElement(StackTraceElement ste) {
            return "\n    " + ste.getClassName() + "." + ste.getMethodName()
                + "(" + ste.getFileName() + ":" + ste.getLineNumber() + ")";
    //================= Client.java =============================================//
    package pkwnet.msgswitch;
    * a simple Swing chat GUI using Java 5 and sockets.
    * @author PKWooster
    * @version 1.0 August 31,2005
    import javax.swing.JFrame;
    import javax.swing.JTextField;
    import javax.swing.JTextArea;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JMenu;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JDialog;
    import javax.swing.SwingUtilities;
    import java.awt.Container;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.BorderLayout;
    import static java.awt.BorderLayout.*;
    client GUI class
    public class Client extends JFrame implements ConnectionListener {
         // swing GUI components
         private JTextField userText = new JTextField(40);
         private JTextArea sessionLog = new JTextArea(24,40);
         private JTextField statusText = new JTextField(40);
         private JPanel outPanel = new JPanel();
         private JScrollPane sessionLogScroll = new JScrollPane(sessionLog);
         private JMenuBar menuBar = new JMenuBar();
         private JMenuItem startItem = new JMenuItem("Start");
         private JMenuItem hostItem = new JMenuItem("Host");
         private JMenuItem aboutItem = new JMenuItem("About");
         private JMenuItem abortItem = new JMenuItem("Abort");
         private JMenuItem exitItem = new JMenuItem("Exit");
         private JMenu fileMenu = new JMenu("File");
         private JMenu helpMenu = new JMenu("Help");
         private Container cp;
         private String address;
        private Connection connection;
        private boolean sendReady = false;
        private boolean nio = false;
         Client() {
        public void start(String address, boolean nio) {
            this.address = address;
            this.nio = nio;
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    runClient();
        private void runClient() {   
            connection = MsgSwitch.getConnection();
            connection.addConnectionListener(this);
              buildMenu();
              cp = getContentPane();
              sessionLog.setEditable(false);
              outPanel.add(new JLabel("Send: "));
              outPanel.add(userText);
              // enter on userText causes transmit
              userText.addActionListener(new ActionListener(){
                   public void actionPerformed(ActionEvent evt){userTyped(evt);}
              cp.setLayout(new BorderLayout());
              cp.add(outPanel,NORTH);
              cp.add(sessionLogScroll,CENTER);
              cp.add(statusText,SOUTH);
              setStatus("Closed");
              addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent evt) {
                    mnuExit();
              pack();
            setVisible(true);
    * attempt to send the contents of the user text field
        private void userTyped(ActionEvent evt) {
            if (sendReady) {
                String txt = evt.getActionCommand()+"\n";
                userText.setText("");
                toSessionLog("> ", txt);
                sendReady = false;
                connection.send(txt);
    * append text to the session log
         private void toSessionLog(String prefix, String txt) {
              sessionLog.append(prefix + txt);
              sessionLog.setCaretPosition(sessionLog.getDocument().getLength() ); // force last line visible
    * build the standard menu bar
         private void buildMenu()
              JMenuItem item;
              // file menu
              startItem.addActionListener(new ActionListener()
              {public void actionPerformed(ActionEvent e){mnuStart();}});
              fileMenu.add(startItem);
              hostItem.addActionListener(new ActionListener()
              {public void actionPerformed(ActionEvent e){mnuHost();}});
              fileMenu.add(hostItem);
              exitItem.addActionListener(new ActionListener()
              {public void actionPerformed(ActionEvent e){mnuExit();}});
              fileMenu.add(exitItem);
              menuBar.add(fileMenu);
              helpMenu.add(aboutItem);
              aboutItem.addActionListener(new ActionListener()
              {public void actionPerformed(ActionEvent e){mnuAbout();}});
              menuBar.add(helpMenu);
              setJMenuBar(menuBar);
    * start and stop communications from start menu
         private void mnuStart() {
            if(connection.getState() ==  Connection.State.CLOSED) {
                connection.connect(address);
            } else {
                connection.disconnect();
    *  prompt user for host in form address:port
        private void mnuHost() {
              String txt = JOptionPane.showInputDialog("Enter host address:port", connection.getAddress());
              if (txt == null)return;
            address = txt;
         private void mnuAbout() {
              JDialog dialog = new JDialog(this, "About Client");
              JTextField text = new JTextField("Simple character client");
            dialog.getContentPane().add(text);
            dialog.pack();
            dialog.setVisible(true);
         // exit menu
         private void mnuExit() {
            exit();
        private void exit() {
              connection.disconnect();
              System.exit(0);
         private void setStatus(String st) {
            statusText.setText(st);
         private void setStatus(Connection.State state) {
            switch(state) {
                case OPENED:
                    startItem.setText("Stop");
                    setStatus("Connected to "+address);
                    break;
                case CLOSED:
                    startItem.setText("Start");
                    setStatus("Disconnected");
                    break;
                case OPENING:
                    setStatus("Connecting to "+address);
                    startItem.setText("Abort");
                    break;
                case CLOSING:
                    setStatus("Disconnecting from "+address);
                    startItem.setText("Abort");
                    break;
        public void stateChanged(final ConnectionEvent event) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    setStatus(event.getState());
        public void dataAvailable(final ConnectionEvent event) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    setStatus(event.getState());
                    String txt = event.getData();
                    if (txt == null) {
                        txt = "$null$";
                    toSessionLog("< ", txt + "\n");   
        public void sendAllowed(final ConnectionEvent event) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    setStatus(event.getState());
                    sendReady = true;
        public void accept(ConnectionEvent event) {
    //========================== Server.java ===============================//
    package pkwnet.msgswitch;
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    * a simple message switch using stream based socket i/o
    * a very simple text message switching program
    * user commands start with $ and consist of blank seperated arguments
    * other lines sent by the user are forwarded
    * $on nickname targets
    *    sign on as nickname, sending to targets
    * $to targets
    *    change target list, reports current value
    * $list nicknames
    *    list status of specified nicknames
    * $list
    *    list all connected users
    * $off
    *    sign off
    * @author PKWooster
    * @version 1.0 September 1, 2005
    public class Server {
        private ConcurrentHashMap<String, User> perUser = new ConcurrentHashMap<String,User>();
        private Timer idleTimer;
        private Connection conn;
        public void listen(int port, final int idleTime, boolean nio) {
            idleTimer = new Timer();
            idleTimer.scheduleAtFixedRate(new TimerTask(){public void run(){oneSec();}},0,1000);
            conn = MsgSwitch.getConnection();
            conn.addConnectionListener(new ConnectionListener() {
                public void stateChanged(ConnectionEvent event) {
                public void dataAvailable(ConnectionEvent event) {
                public void sendAllowed(ConnectionEvent event) {
                public void accept(ConnectionEvent event) {
                    Connection uconn = event.getConnection();
                    new User(uconn, perUser, idleTime);
            conn.listen(port);
            idleTimer.cancel();
        private void oneSec() {
            Collection<User> uc = perUser.values();
            for(User u : uc) {
                u.oneSec();
    //================= User.java  ==============================================//
    package pkwnet.msgswitch;
    import java.io.*;
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.logging.Logger;
    import java.util.logging.Level;
    * defines the processing for a message switch user
    * @author PKWooster
    * @version 1.0 June 15,2004
    public class User implements ConnectionListener {
        private ConcurrentHashMap<String, User> perUser;
        private String name;
        private String address;
        private boolean signedOn = false;
        private String[] targets;
        private AtomicInteger remainingTime;
        private int idleTime;
        Connection conn;
        Logger logger;
      * construct a user, link it to its connection and put it in the perUser table
        User(Connection conn, ConcurrentHashMap<String,User>p, int idle) {
            this.conn = conn;
            logger = Logger.getLogger("msgswitch.user");
            conn.addConnectionListener(this);
            address = conn.getAddress();
            logger.info("creating user " + address);
            perUser = p;
            idleTime = idle;
            remainingTime = new AtomicInteger(idleTime);
            rename(address);
            targets = new String[0];
    * process state changes
        public void stateChanged(ConnectionEvent event) {
            if(event.getState() == Connection.State.CLOSED) {
                close(false);
    * data is available, process commands and forward other data.
        public void dataAvailable(ConnectionEvent event) {
            String msg = event.getData();
            if (msg.startsWith("$")) {
                doCommand(msg);
            } else {
                forward(msg);
            remainingTime.set(idleTime);
    * do nothing for sendAllowed events
        public void sendAllowed(ConnectionEvent event) {
    * do nothing for accept events
        public void accept(ConnectionEvent event) {
    * called once per second by the server main thread.
        public void oneSec() {
            if(idleTime != 0 && 1 > remainingTime.decrementAndGet()) {
                close(true);
    * send a message
        private void send(String msg) {
            conn.send(msg);
            remainingTime.set(idleTime);
    * forward data messages to other users
    * @param txt the message to send
        private void forward(String txt) {
            txt = name+": "+txt + "\n";
            if(0 < targets.length) {
                for(String target :targets) {
                    User user = perUser.get(target);
                    if(user != null) {
                        user.send(txt);
            } else {
                for (User user : perUser.values()) {
                    if (user != this) {
                        user.send(txt);
    * execute command messages, commands start with a $
    * and contain arguments delimited by white space.
    * @param command the command string
        private void doCommand(String command) {
            boolean good = false;
            command = command.substring(1).trim();
            if(command.length() > 0) {
                String [] args = command.split("\\s+");
                if(args[0].equals("on")) {
                    good = signOn(args);
                } else if(args[0].equals("off")) {
                    good = signOff(args);
                } else if(args[0].equals("list")) {
                    good = listUsers(args);
                } else if(args[0].equals("to")) {
                    good = setTargets(args,1);
                } else if(args[0].equals("idle")) {
                    good = setIdle(args);
                if(!good) {
                    send("invalid command=" + command + "\n");
    * sign on command
        private boolean signOn(String [] args) {
            boolean good = false;
            if(args.length >1) {
                String nm = args[1];
                logger.info("signing on as: " + nm);
                if(rename(nm)) {
                    conn.setName(name);
                    send("Signed on as " + name + "\n");
                    signedOn = true;
                    good = true;
                    setTargets(args,2);
                } else {
                    send("name="+nm+" already signed on\n");
            return good;
    * set forwarding targets
        private boolean setTargets(String [] args, int start) {
            if(start < args.length) {
                targets = new String[args.length-start];
                System.arraycopy(args, start, targets, 0, targets.length);
            String str = "to=";
            for(String target : targets) {
                str += (target + " ");
            send(str+"\n");
            return true;
    * set idle timeout
        private boolean setIdle(String[] args) {
            try {
                idleTime = new Integer(args[1]).intValue();
                remainingTime.set(idleTime);
                send("idle time set to "+idleTime+"\r\n");
                return true;
            } catch(NumberFormatException exc) {
                return false;
    * sign off
        private boolean signOff(String [] args) {
            close(true);
            return true;
    * list connected users
        private boolean listUsers(String [] args) {
            TreeSet<String> allUsers = new TreeSet<String>(perUser.keySet());
            HashSet<String> t = new HashSet<String>(Arrays.asList(targets));
            LinkedList<String> users;
            String response = "On,Target,Nickname\n";
            if(args.length < 2) {
                users = new LinkedList<String>(allUsers);
            } else {
                users = new LinkedList<String>();
                for (int i = 1; i < args.length; i++) {
                    users.add(args);
    for(String username : users) {
    if(username.equals(name)) {
    response += "*,";
    } else {
    response += (allUsers.contains(username) ? "y," : "n,");
    response += (t.contains(username) ? "y," : "n,");
    response += (username + "\n");
    send(response);
    return true;
    * rename this user, first we attempt to add the new name then we remove
    * the old one. Both names will be registered for a short while.
    * @param newname the new name for this user
    * @return true if the rename was successful
    private boolean rename(String newname) {
    boolean b = false;
    logger.info("rename name="+name+" newname="+newname);
    if (name != null && name.equals(newname)) {
    b = true;
    } else if (null == perUser.putIfAbsent(newname, this)) {
    if (name != null) {
    perUser.remove(name);
    name = newname;
    b = true;
    return b;
    * delete from perUser and close our connection
    private void close(boolean disconnect) {
    logger.info("closing user "+name);
    perUser.remove(name);
    if (disconnect) {
    conn.disconnect();
    //====================== Connection.java ===============================//
    package pkwnet.msgswitch;
    import java.util.HashSet;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.logging.Logger;
    import java.util.logging.Level;
    public abstract class Connection {
    public enum State {CLOSED, OPENING, OPENED, CLOSING}
    private HashSet<ConnectionListener> listeners = new HashSet<ConnectionListener>();
    private State state = State.CLOSED;
    private String host = "127.0.0.1";
    private int port = 6060;
    private String name = "unconnected";
    public Connection() {
    public abstract void listen(int port);
    public abstract void connect(String address);
    public abstract void disconnect();
    public abstract void send(String message);
    public void addConnectionListener(ConnectionListener listener) {
    listeners.add(listener);
    public void removeConnectionListener(ConnectionListener listener) {
    listeners.remove(listener);
    protected void fireDataAvailable(String data) {
    for (ConnectionListener listener : listeners) {
    listener.dataAvailable(new ConnectionEvent(this, state, data));
    private void fireStateChanged() {
    for (ConnectionListener listener : listeners) {
    listener.stateChanged(new ConnectionEvent(this, state));
    protected void fireSendAllowed() {
    for (ConnectionListener listener : listeners) {
    listener.sendAllowed(new ConnectionEvent(this, state));
    protected void fireAccept(Connection conn) {
    for (ConnectionListener listener : listeners) {
    listener.accept(new ConnectionEvent(this, conn));
    protected void setState(State state) {
    if (this.state != state) {
    this.state = state;
    fireStateChanged();
    public State getState() {
    return state;
    protected void setAddress(String address) {
              int n = address.indexOf(':');
              String pt = null;
    setName(address);
    if(n == 0) {
                   host = "127.0.0.1";
                   pt = address.substring(1);
              else if(n < 0) {
                   host = address;
                   port = 5050;
              } else {
    host = address.substring(0,n);
                   pt = address.substring(n+1);
    if (pt != null) {
    try {
    port = Integer.parseInt(pt);
    } catch (NumberFormatException e) {
    port = -1;
    public String getName() {
    return name;
    public void setName(String value) {
    name = value;
    public String getAddress() {
    return host + ":" + port;
    public String getHost() {
    return host;
    public void setPort(int value) {
    port = value;
    public int getPort() {
    return port;
    //=================== ConnectionEvent.java ================================//
    package pkwnet.msgswitch;
    public class ConnectionEvent extends java.util.EventObject {
    private final String data;
    private final Connection.State state;
    private final Connection conn;
    public ConnectionEvent(Object source, Connection.State state, String data, Connection conn) {
    super(source);
    this.state = state;
    this.data = data;
    this.conn = conn;
    public ConnectionEvent(Object source, Connection.State state, String data) {
    this(source, state, data, null);
    public ConnectionEvent(Object source, Connection.State state) {
    this(source, state, null, null);
    public ConnectionEvent(Object source, Connection conn) {
    this(source, conn.getState(), null, conn);
    public Connection.State getState() {
    return state;
    public String getData() {
    return data;
    public Connection getConnection() {
    return conn;
    //============================ ConnectionListener.java ===================//
    package pkwnet.msgswitch;
    public interface ConnectionListener extends java.util.EventListener {
    public void stateChanged(ConnectionEvent event);
    public void dataAvailable(ConnectionEvent event);
    public void sendAllowed(ConnectionEvent event);
    public void accept(ConnectionEvent event);
    //============================ StreamConnection.java ===================//
    package pkwnet.msgswitch;
    import java.net.Socket;
    import java.net.ServerSocket;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.IOException;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.logging.Logger;
    import java.util.logging.Level;
    * provides stream socket i/o of character strings
    * @author PKWooster
    * @version 1.0 September 1, 2005
    public class StreamConnection extends Connection {
    private Socket sock;
    private BufferedReader in;
    private BufferedWriter out;
    private Thread recvThread = null;
    private Thread sendThread = null;
    protected LinkedBlockingQueue<String> sendQ;
    Logger logger;
    public StreamConnection() {
    super();
    logger = Logger.getLogger("msgswitch.stream");
    sendQ = new LinkedBlockingQueue<String>();
    * open a socket and start i/o threads
    public void connect(String ipAddress) {
    setAddress(ipAddress);
    try {
    sock = new Socket(getHost(), getPort());
    connect(sock);
    } catch (IOException e) {
    logger.log(Level.SEVERE, "Connection failed to=" + ipAddress, e);
    private void connect(Socket sock) {
    this.sock = sock;
    String ipAddress = getAddress();
    try {
    in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
    out = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
    recvThread = new Thread(new Runnable() {
    public void run() {
    doRecv();
    },"Recv." + getName());
    sendThread = new Thread(new Runnable() {
    public void run() {
    doSend();
    },"Send."+getName());
    sendThread.start();
    recvThread.start();
    setState(State.OPENED);
    } catch(IOException e) {
    logger.log(Level.SEVERE, "Connection failed to="+ipAddress, e);
    public void listen(int port) {       
    StreamConnection sconn;
    setPort(port);
    try {
    ServerSocket ss = new ServerSocket(port);
    while(true) {
    Socket us = ss.accept();
    sconn = new StreamConnection();
    String ipAddress = us.getInetAddress() + ":" + us.getPort();
    sconn.setAddress(ipAddress);
    sconn.connect(us);
    fireAccept(sconn);
    } catch(Exception e) {
    logger.log(Level.SEVERE, "listen failed", e);
    * close the socket connection
    public void disconnect() {
    logger.fine("disconnect sock=" + sock + " state="+ getState());
    if(getState() == State.OPENED) {
    setState(State.CLOSING);
    try {
    sock.shutdownOutput();
    } catch(IOException ie) {
    logger.log(Level.SEVERE, "showdown failed", ie);
    } else if(getState() != State.CLOSED) {
    try {
    sock.close();
    } catch(Exception e) {
    logger.log(Level.SEVERE, "close failed", e);
    if (sendThread.isAlive()) {
    sendThread.interrupt();
    sendQ.clear();
    setState(State.CLOSED);
    public void send(String message) {
    if (getState() == State.OPENED) {
    try {
    sendQ.put(message);
    } catch(InterruptedException e) {
    logger.log(Level.SEVERE, "sendQ put interrupted", e);
    setState(State.CLOSING);
    disconnect();
    * sets the public name of this connection
    public void setName(String name) {
    super.setName(name);
    if (sendThread != null) {
    try {
    recvThread.setName("recv." + name);
    sendThread.setName("send." + name);
    } catch(Exception e) {
    logger.log(Level.SEVERE, "nameing threads failed", e);
    * the main loop for the send thread
    private void doSend() {
    String msg;
    boolean running = true;
    while (running) {
    if (sendQ.size() == 0) {
    fireSendAllowed();
    try {
    msg = sendQ.take();
    out.write(msg);
    out.flush();
    } catch(Exception e) {
    if (getState() == State.OPENED) {
    logger.log(Level.SEVERE, "write failed", e);
    setState(State.CLOSING);
    disconnect();
    running = false;
    * the main loop for the receive thread
    private void doRecv() {
    String inbuf;
    while (getState() == State.OPENED) {
    try {
    inbuf = in.readLine();
    } catch(Exception e) {
    if (getState() == State.OPENED) {
    logger.log(Level.SEVERE, "readline failed", e);
    inbuf = null;
    if(inbuf == null) {
    logger.fine("null received on: " + getAdd

    Here are three of them:
    NIO server
    NIO client
    Multithreaded server
    The stream based client example seems to have been deleted, probably lost in the troll wars. I also posted a new Simple multithreaded server that uses the same protocol. As the client is missing, I'll repost it.

  • [java.nio] StreamCorruptedException when deserializing objects

    Hello everybody!
    I made a messaging (chat) program using java.io where all the client-server communication is done by serializing small objects. Now I would like to covert the server side to the NIO concept and I'm already struck. I successfully pass objects to the client and the client deserializes them, but only the first one! When it try to read the second it fails with a StreamCorruptedException.
    Here�s a sample (testing) code. In the server run() method I first serialize a string, then get its byte array from ByteArrayOutputStream and in the loop periodically send this byte array through the channel. On the client side I just read the deserialized object.
    Server run():
    public void run() {
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject("abcdefgh");
                byte[] objectArr = baos.toByteArray();
                baos.close();
                oos.close();
                ByteBuffer buff = ByteBuffer.allocate(objectArr.length);
                buff.put(objectArr);
                buff.flip();
                while(true) {
                    selector.select();
                    Set keys = selector.selectedKeys();
                    for (Object o : keys) {
                        SelectionKey key = (SelectionKey)o;
                        if (key.isAcceptable()) {
                            ServerSocketChannel server = (ServerSocketChannel) key.channel();
                            clientChannel = server.accept();
                            if (clientChannel == null)
                                continue;
                            clientChannel.configureBlocking(false);
                            SelectionKey clientKey = clientChannel.register(selector, SelectionKey.OP_WRITE);
                        } else if (key.isWritable()) {
                            SocketChannel client = (SocketChannel) key.channel();
                            if (buff.hasRemaining()) {
                                client.write(buff);
                            } else {
                                buff.clear();
                                buff.put(objectArr);
                                buff.flip();
                    try {
                        Thread.currentThread().sleep(2000);
                    } catch (InterruptedException e) {
                        return;
            } catch (IOException e) {
                e.printStackTrace();
        }Client run():
    public void run() {
            try {
                soc = new Socket("localhost", 4000);
                ObjectInputStream ois = new ObjectInputStream(soc.getInputStream());
                while(true) {
                    Object d = ois.readObject();
                    System.out.println("data = " + d.toString());
            } catch (Exception ex) {
                ex.printStackTrace();
        }At the second read I get a StreamCorruptedException.
    Apart from this I would like some hints in how to implement the application with NIO. For example how can I tell the objects apart on the client side � should I send every time a byte array before the object, which tells the length of the next coming object? This is probably not a 100% bulletproof solution and presents additional data transfer?
    Than you in advance!

    OK, I found a solution but I don't like it, because I don't understand it.
    The ObjectOutputStream adds a header (4 bytes) to the stream - if I send the array with those four bytes I get an StreamCorruptedException. If I send the array without the header I also get a StreamCorruptedException: "invalid stream header".
    If I reconstruct the object, by calling ObjectOutputStream.writeObject() and get it's byte array from ByteArrayOutputStream.toByteArray(), every time I have to fill the ByteBuffer, then it works.
    Here's the modified sending block, for the above example:
    } else if (key.isWritable()) {
                            SocketChannel client = (SocketChannel) key.channel();
                            if (buff.hasRemaining()) {
                                client.write(buff);
                            } else {
                                //* ---- added code ---------
                                baos.reset();
                                oos.writeObject("abcdefgh");
                                objectArr = baos.toByteArray();
                                buff.clear();
                                buff.put(objectArr);
                                buff.flip();
                        }   I really don't understand why I have to write the object in the object stream every time. I used ObjectOS and ByteArrayOS, to get the object byte array and then I thought I could forget about those streams and use this array to fill the ByteBuffer. What changes if I send the object through this process with every iteration (and how this harms speed - it's like sending everything twice)? If someone would explain this to me I would appreciate it much.

  • Converting from CP1252 (Windows) to ISO 8859-1 doesn't work with java.nio?

    Hi
    I'm trying to write some code that checks whether an InputStream contains only characters with a given encoding. I'm using java.nio for that. For tests, I downloaded some character set examples from http://www.columbia.edu/kermit/csettables.html
    When creating the CharsetDecoder, I want to get all errors:
        Charset charset = Charset.forName( encoding );
        CharsetDecoder decoder = charset.newDecoder();
        decoder.onMalformedInput( CodingErrorAction.REPORT );
        decoder.onUnmappableCharacter( CodingErrorAction.REPORT );I then read an InputStream and try to convert it. If that fails, it can't contain the desired encoding:
        boolean isWellEncoded = true;
        ByteBuffer inBuffer = ByteBuffer.allocate( 1024 );
        ReadableByteChannel channel = Channels.newChannel( inputStream );
        while ( channel.read( inBuffer ) != -1 )
          CharBuffer decoded = null;
          try
            inBuffer.flip();
            decoded = decoder.decode( inBuffer );
          catch ( MalformedInputException ex )
            isWellEncoded = false;
          catch ( UnmappableCharacterException ex )
            isWellEncoded = false;
          catch ( CharacterCodingException ex )
            isWellEncoded = false;
          if ( decoded != null )
            LOG.debug( decoded.toString() );
          if ( !isWellEncoded )
            break;
          inBuffer.compact();
        channel.close();
        return isWellEncoded;Now I want to check whether a file containing Windows 1252 characters is ISO-8859-1. From my point of view, the code above should fail when it gets to the Euro symbol (decimal 128), since that's not defined in ISO-8859-1.
    But all I get is a ? character instead:
    (})  125  07/13  175  7D                 RIGHT CURLY BRACKET, RIGHT BRACE
    (~)  126  07/14  176  7E                 TILDE
    [?]  128  08/00  200  80  EURO SYMBOL
    [?]  130  08/02  202  82  LOW 9 SINGLE QUOTEI also tried to replace the faulty character, using
        decoder.onUnmappableCharacter( CodingErrorAction.REPLACE );
        decoder.replaceWith("!");but I still get the question marks.
    I'm probably doing something fundamentally wrong, but I dont get it :-)
    Any help is greatly appreciated!
    Eric

    As a suggestion....create a complete example demonstrating the problem. It shouldn't have channel in it since that wouldn't appear to be the problem (decoding is.) You should create the byte array in the example code - populate it with the byte sequence that you think should work. And your code should then demonstrate that it doesn't. Then post that.

  • Synchronous IO with nio

    Hello,
    I have been programming in Java for a while but today is my first shot at NIO.
    I'm implementing a custom protocol over TCP between a java server and several Java and C clients. The classical one-thread-per-client approach works with a couple of test connections, but I'm afraid it will not scale:
    - I will not have control on all clients programs
    - I don't know yet the expected traffic
    - I might introduce bugs as well in the sever program and leak sockets and threads
    Here is the code for the classical approach:
    ServerSocket server.accept()  = ...;
    Socket client = server.accept();
    Thread clientThread = new ClientThread(client);
    clientThread.start();Where ClientThread's run method deos the following:
    BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
    while (isConnected) {
        String pdu = reader.readLine();
        storeClientInfo(pdu);
    }The key is that in order to make for a very simple protocol we designed it so that each PDU is one line of text, sent over TCP. Reading one PDU is therefiore a synchronous operation.
    In order to provision scaling to many clients, we are trying to reimplement it using NIO.
    We use a Selector to wait for requests, and once accepted, we register the Selector with the created SocketChannel (one per client).
    One single thread dequeues reads selected by the Selector, but we are still trying to read using the synchronous BufferredReader.
    When a SocketChannel has readable data, we create a Buffered reader like this:
    BufferedReader reader = new BufferedReader(new InputStreamReader(socketChannel.socket().getInputStream()));
    String pdu = reader.readLine(); //  throws IllegalBlockingModeException
    }And as you probably expect, we get an IllegalBlockingModeException when reading the line (synchronous operation) over the (asynchronous) socket.
    If my understanding is correct, the SocketChannel has to be put in non-blocking mode to be selectable by the Selector (otherwise the register(...) call throws an IllegalBlockingStateException), but it cannot be read synchronously in this non-blocking mode.
    Is there any way I can connect a BufferedReader to a non-blocking SocketChannel somehow?
    There would be an alternative approach, where the listeing thread reads the data from the SocketChannel into a ByteBuffer, then stuffs those bytes into a PipedOutputStream, and build a reader over a PipedInputStream.
    The problem is that in this case, we need, again, one thread per client to read the data froml the reader...
    There's a third approach, where we would use the "attachment" feature of SocketChannel.register() and SelectedKey; in this approach, the attachment could be a stringBuffer; each time the Selector warns us that data is readable, the data would be read from the SocketChannel into a ByteBuffer. then added to the StringBuffer. We would have to analyze the StringBuffer's content to find out whether it contains a whole line, and only then extract this line as the "PDU".
    Is this a recommended approach?
    Thanks in advance, and regards,
    J.
    Message was edited by: jduprez (some code markers had been swallowed)
    Message was edited by:
    jduprez

    OK, thanks.
    I implemented this third approach, and it works under moderate load. The difficulty though, is that what I can read from the channel is a chunk of binary data, possibly incomplete, and that possibly doesn't even translate to valid chars (for example, a 16-bits char may be cut in-between and I get only the first byte).
    That orients me to a binary protocol (at least, to a protocol where I can identify "end of message " markers at the binary level).
    Alternately, if I can ensure all my messages fit a UDP packet, I'd better stuff the String in a UDP packet on the client end, and decode a String from the UDP received (atomically) on the server end.
    I'd lose TCP's relative reliability, but simplify the programming model for the protocol handling...
    I'm still free to choose the transport at this step of the project...
    Any recommendation?

  • Identifying and managing clients in nonblocking NIO socket programming

    Here's my beef. When I write a Server using a thread for every new connection that comes in, I can remember everything for each client in its respective thread. I can have a table entry in a MYSQL database for each client which each thread can look up by a remembered id. I can direct packets from a different application to a specific client by passing a message to the thread associated with the client. But, in this implementation, the client-server setup will need to have a master-slave relationship where one is always reading, and can talk on the network only in response.
    I like the NIO selector way of doing things, but I do not get a memory method to deal with specific clients. How do I, for example,
    direct packets to a specific client.?
    recognize incoming packet info and make sense of its context in relation to past messages to and from the same client?
    maintain one-to-one correspondence between a MYSQL database table entry and a specific client?
    Could somebody explain this to me how I can maintain a client environment, and a client state machine with memory?
    Thanks
    Anil

    cloud9ine wrote:
    Here's my beef. When I write a Server using a thread for every new connection that comes in, I can remember everything for each client in its respective thread. I can have a table entry in a MYSQL database for each client which each thread can look up by a remembered id. I can direct packets from a different application to a specific client by passing a message to the thread associated with the client. But, in this implementation, the client-server setup will need to have a master-slave relationship where one is always reading, and can talk on the network only in response.
    I like the NIO selector way of doing things, but I do not get a memory method to deal with specific clients. How do I, for example,
    direct packets to a specific client.?
    recognize incoming packet info and make sense of its context in relation to past messages to and from the same client?
    maintain one-to-one correspondence between a MYSQL database table entry and a specific client?
    Could somebody explain this to me how I can maintain a client environment, and a client state machine with memory?
    Thanks
    AnilYou will use select() and SelectionKey when you deal with NIO. The SelectionKey has an attach method that you can use to associate the client with something, e.g. a session. Your Session class can contain all that you now have in your thread.
    Kaj

  • NIO SocketChannel truncating write from MappedByteBuffer

    Hello!
    I'm running SDK build 1.4.1_01-b01 on Win2K (SP3), but I can also duplicate this on Linux (2.4 kernel).
    I'm writing a simple file server, and it uses the following code:FileInputStream fis = new FileInputStream(file);
    FileChannel fc = fis.getChannel();
    MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
    sc.write(buffer);
    sc.close()However applications that download (not just Java applications) do not receive the entire file. The server reports sending all of the bytes (sc.write() returns the value from fc.size()) but it is not all received byt the client downloading (I'm using wget on a Linux box).
    NIO has no way to flush, so... ok this is where I'm lost. Am I doing this all wrong?
    I even triedsc.socket().getOutputStream().flush();to no avail.
    Another similar example of this problem is the code from this article at JavaWorld:
    http://www.javaworld.com/javaworld/jw-09-2001/jw-0907-merlin.html
    The zip file contains only one class file that runs, except serving up say a 300kB Jar file does not work.

    Firstly thankyou very much for your time so far...
    I hope I'm not tripping over the protocol, I have implemented a simple HTTP server.
    The important section of code (very cut down - no log messages and less Exception handling) is:public class HttpGetHandler extends Thread {
        private SocketChannel sc;
        private File file;
        public HttpGetHandler_1(SocketChannel pSocketChannel, File pFile) {
            super("HttpGetHandler");
            this.sc = pSocketChannel;
            this.file = pFile;
            start();
        public void run() {
            try {
                // Open the file and then get a channel from the stream
                FileInputStream fis = new FileInputStream(file);
                FileChannel fc = fis.getChannel();
                // Get the file's size and then map it into memory
                long sz = (int) fc.size();
                // Create Header
                String header = new String(
                "HTTP/1.0 200 OK\r\n"
                + "Content-Length: " + sz + "\r\n"
                transmitBuffer(ByteBuffer.wrap(header.getBytes()));
                long position = 0;
                while (position < sz) {
                    MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, position, sz - position);
                    transmitBuffer(buffer);
                    position += buffer.capacity();
            } catch (Exception e) {
            } finally {
                try {
                    // HACK
                    try {
                        Thread.currentThread().sleep(20000);
                    } catch (InterruptedException e) {
                        log.warn("InterruptedException", e);
                    sc.close();
                } catch (IOException e) {
        private void transmitBuffer(ByteBuffer pBuffer) throws IOException {
            while (pBuffer.hasRemaining()) {
                sc.write(pBuffer);
    }

  • Java NIO client

    I need to make the server is able to hold about 500 connections and operates on a single thread. The server itself should make all the connections. Where can I find examples of finished implementations?

    I have an example, but it does not work
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.nio.ByteBuffer;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.SocketChannel;
    import java.nio.channels.spi.SelectorProvider;
    import java.util.*;
    public class NioClient implements Runnable {
         // The host:port combination to connect to
         private InetAddress hostAddress;
         private String host;
         private int port;
         // The selector we'll be monitoring
         private Selector selector;
         // The buffer into which we'll read data when it's available
         private ByteBuffer readBuffer = ByteBuffer.allocate(8192);
         // A list of PendingChange instances
         private List pendingChanges = new LinkedList();
         // Maps a SocketChannel to a list of ByteBuffer instances
         private Map pendingData = new HashMap();
         // Maps a SocketChannel to a RspHandler
         private Map rspHandlers = Collections.synchronizedMap(new HashMap());
         public NioClient() {
              try {this.selector = this.initSelector();} catch(IOException e){}
         public void connect(String host, int port, RspHandler handler) throws IOException {
              this.hostAddress = hostAddress;
              this.host = host;
              this.port = port;
              this.send("$Hello |".getBytes(), handler);
         public void send(byte[] data, RspHandler handler) throws IOException {
              // Start a new connection
              SocketChannel socket = this.initiateConnection();
              // Register the response handler
              this.rspHandlers.put(socket, handler);
              // And queue the data we want written
              synchronized (this.pendingData) {
                   List queue = (List) this.pendingData.get(socket);
                   if (queue == null) {
                        queue = new ArrayList();
                        this.pendingData.put(socket, queue);
                   queue.add(ByteBuffer.wrap(data));
              // Finally, wake up our selecting thread so it can make the required changes
              this.selector.wakeup();
              handler.waitForResponse();
         public void run() {
              while (true) {
                   try {
                        // Process any pending changes
                        synchronized (this.pendingChanges) {
                             Iterator changes = this.pendingChanges.iterator();
                             while (changes.hasNext()) {
                                  ChangeRequest change = (ChangeRequest) changes.next();
                                  switch (change.type) {
                                  case ChangeRequest.CHANGEOPS:
                                       SelectionKey key = change.socket.keyFor(this.selector);
                                       key.interestOps(change.ops);
                                       break;
                                  case ChangeRequest.REGISTER:
                                       change.socket.register(this.selector, change.ops);
                                       break;
                             this.pendingChanges.clear();
                        // Wait for an event one of the registered channels
                        this.selector.select();
                        // Iterate over the set of keys for which events are available
                        Iterator selectedKeys = this.selector.selectedKeys().iterator();
                        while (selectedKeys.hasNext()) {
                             SelectionKey key = (SelectionKey) selectedKeys.next();
                             selectedKeys.remove();
                             if (!key.isValid()) {
                                  continue;
                             // Check what event is available and deal with it
                             if (key.isConnectable()) {
                                  this.finishConnection(key);
                             } else if (key.isReadable()) {
                                  this.read(key);
                             } else if (key.isWritable()) {
                                  this.write(key);
                   } catch (Exception e) {
                        e.printStackTrace();
         private void read(SelectionKey key) throws IOException {
              SocketChannel socketChannel = (SocketChannel) key.channel();
              // Clear out our read buffer so it's ready for new data
              this.readBuffer.clear();
              // Attempt to read off the channel
              int numRead;
              try {
                   numRead = socketChannel.read(this.readBuffer);
              } catch (IOException e) {
                   // The remote forcibly closed the connection, cancel
                   // the selection key and close the channel.
                   key.cancel();
                   socketChannel.close();
                   return;
              System.out.println("READ");
              if (numRead == -1) {
                   // Remote entity shut the socket down cleanly. Do the
                   // same from our end and cancel the channel.
                   key.channel().close();
                   key.cancel();
                   return;
              // Handle the response
              this.handleResponse(socketChannel, this.readBuffer.array(), numRead);
         private void handleResponse(SocketChannel socketChannel, byte[] data, int numRead) throws IOException {
              // Make a correctly sized copy of the data before handing it
              // to the client
              byte[] rspData = new byte[numRead];
              System.arraycopy(data, 0, rspData, 0, numRead);
              // Look up the handler for this channel
              RspHandler handler = (RspHandler) this.rspHandlers.get(socketChannel);
              // And pass the response to it
              if (handler.handleResponse(rspData)) {
                   // The handler has seen enough, close the connection
                   socketChannel.close();
                   socketChannel.keyFor(this.selector).cancel();
         private void write(SelectionKey key) throws IOException {
              SocketChannel socketChannel = (SocketChannel) key.channel();
              synchronized (this.pendingData) {
                   List queue = (List) this.pendingData.get(socketChannel);
                   // Write until there's not more data ...
                   while (!queue.isEmpty()) {
                        ByteBuffer buf = (ByteBuffer) queue.get(0);
                        socketChannel.write(buf);
                        if (buf.remaining() > 0) {
                             // ... or the socket's buffer fills up
                             break;
                        queue.remove(0);
                   if (queue.isEmpty()) {
                        // We wrote away all data, so we're no longer interested
                        // in writing on this socket. Switch back to waiting for
                        // data.
                        key.interestOps(SelectionKey.OP_READ);
         private void finishConnection(SelectionKey key) throws IOException {
              SocketChannel socketChannel = (SocketChannel) key.channel();
              // Finish the connection. If the connection operation failed
              // this will raise an IOException.
              try {
                   socketChannel.finishConnect();
              } catch (IOException e) {
                   // Cancel the channel's registration with our selector
                   System.out.println(e);
                   key.cancel();
                   return;
              // Register an interest in writing on this channel
              key.interestOps(SelectionKey.OP_WRITE);
         private SocketChannel initiateConnection() throws IOException {
              // Create a non-blocking socket channel
              SocketChannel socketChannel = SocketChannel.open();
              socketChannel.configureBlocking(false);
              // Kick off connection establishment
              socketChannel.connect(new InetSocketAddress(this.host, this.port));
              // Queue a channel registration since the caller is not the
              // selecting thread. As part of the registration we'll register
              // an interest in connection events. These are raised when a channel
              // is ready to complete connection establishment.
              synchronized(this.pendingChanges) {
                   this.pendingChanges.add(new ChangeRequest(socketChannel, ChangeRequest.REGISTER, SelectionKey.OP_CONNECT));
              return socketChannel;
         private Selector initSelector() throws IOException {
              // Create a new selector
              return SelectorProvider.provider().openSelector();
    public class RspHandler {
         private byte[] rsp = null;
         public synchronized boolean handleResponse(byte[] rsp) {
              this.rsp = rsp;
              this.notify();
              return true;
         public synchronized void waitForResponse() {
              while(this.rsp == null) {
                   try {
                        this.wait();
                   } catch (InterruptedException e) {
              System.out.println(new String(this.rsp));
    }          NioClient NioClient = new NioClient();
              Thread t = new Thread(NioClient);
              t.setDaemon(true);
              t.start();
              RspHandler handler = new RspHandler();          
              NioClient.connect("69.28.156.250", 27040, handler);
              NioClient.connect("72.165.61.188", 27040, handler);
              NioClient.connect("208.111.133.84", 27011, handler);
              NioClient.connect("72.165.61.136", 27012, handler);
    Edited by: 915967 on 01.08.2012 7:07

  • Java NIO Vs Normal IO

    hi ppl...i want to know when v should prefer nio over normal io. I read somewhere that only if you have to deal with a lot of connections simultaneously you should consider using NIO. as an example it said that a web spider which needs to process a few million connections simultaneously NIO should be preferred. Now in my project i need to have around 750 simultaneous connections. Should i use NIO or traditional IO ?

    There is not enough information given about the
    specifics of this situation to be making such broad
    claim that it will help.I got enougth information. NIO was introduced because traditional Java I/O was found lacking. Traditional I/O is good for reading and writing a few files but that's not what the OP will be attempting. From the NIO proposal documentation:
    2.3 What needs of the Java community will be addressed by the proposed specification?
    * The proposed specification will satisfy several long-standing needs of the Java community.
    * The scalable I/O API will make it easier to write production-quality web and application servers that scale well to thousands of open connections and can easily take advantage of multiple processors;
    * The fast buffered binary I/O API will make it easier to write high-performance, I/O-intensive programs that manipulate streams or files of binary data;
    * The fast buffered character I/O API will simplify the efficient handling of character streams and files; it will also bring regular expressions and a compact notation for formatted output to the Java platform, putting it on a par with other popular platforms such as Perl;
    * The character-set converter API will give developers direct access the platform's built-in character-set converters and will also provide for the easy "plugging in" of new converters;
    * The new set of I/O exceptions will make it easier to write programs that recover from different types of I/O failures in different ways, and to write user interfaces that behave consistently on different platforms when I/O failures occur; and
    * The new filesystem interface will work more consistently across platforms, will make it easier to write programs that gracefully handle the failure of filesystem operations, will provide more efficient access to a larger set of file attributes, will allow developers of sophisticated applications to take advantage of platform-specific features when absolutely necessary, and will allow support for non-native filesystems, such as network filesystems, to be "plugged in" to the platform.
    2.4 Why aren't these needs met by existing specifications?
    Some of the above needs can be met by using existing APIs together with a significant amount of custom code. It is possible, for example, to write a class that implements the DataInput interface and runs about eight times faster than the built-in DataInputStream class. The Java community would be better served if the Java platform made this sort of work unnecessary.
    Some of the above needs can be met by using existing APIs in fragile, implementation-specific ways. To recover from specific types of I/O errors, for example, developers sometimes write code that dissects the message strings of generic IOException objects. This technique may work with a particular implementation of Java on a particular operating system, but it is not very portable. A different implementation on a different operating system may, in a given situation, throw an IOException object with a completely different message string.
    Finally, most of the above needs cannot be met simply because the required functionality is not provided by the current I/O APIs.
    In summary. If you're doing serious I/O (like 1000 open connections) go for NIO. It's also easier to start with NIO right away to get used to it than it is to first use traditional I/O only to find you need to upgrade later on.

Maybe you are looking for

  • Stuck in a limbo: can't install Safari or Lion/Mountain Lion, can't access App Store

    If someone would take up this challenge and attempt to solve it with me, I would appreciate it! I have troubleshooted for 2 days now to no avail. This is what happened: 1) I accidentally installed Safari 6.0, even if I have Lion 10.7. which doesn't r

  • [Solved] KDE 4 and Amarok 1.4 Media Keys

    I've been using KDE 4.2 since it was released. I had installed Amarok 2.0.1 via AUR and was having issues with that version not being compatible with the newest libgpod. I upgraded to 2.0.2 and now Amarok's not able to build my collection database. A

  • Viewing photo`s on TV

    Can anybody help me to view photo`s on my TV. I have plugged the yellow jack in2 the video on the tele and opened my pics on my phone but nothing appears. My phone is a N95 Thanks.

  • Will  a Magic mouse work with a Ipad?

    I was told you can pair a magic mouse with a ipad! Tried to sync , but it won't work. Someone else told me you have to jailbreak the ipad. Is this the only way?

  • Configuration Adobe Document Services Portal 7.3

    Hello colleagues, I has been this guie, http://scn.sap.com/people/sunny.pahuja2/blog/2012/01/04/ads-configuration-in-netweaver-73 The RFC ADS in transaction SM50 dont work properly, Can you help me? Thanks