Java NIO, unblocking server with multiple clients.

Hello!

Im only a hobbyer with Java, no computer schools at all.

is this code about everything i need to go studying the best way to do a server with multiple clients.

				 while(true)
				 {
				  Socket incoming = s.accept();
				  Runnable r = new ThreadedHandler(incoming);
				  
				  Thread t = new Thread(r);
				  t.start();
				 }
				 

				 class ThreadedHandler implements Runnable
				 {
				 ...
				 public void run(){
				 try{
				 	 InputStream inStream = incoming.getInputStream();
					 OutputStream outStream = incoming.getOuputStream();
					 // process input and send response
					 incoming.close()
				 
				 
				 }
				 catch(IOException e){
				 
				 
				 }
				 }
				 }
				 

question -> should it the next line rather be like ->
class ThreadedHandler ( Socket incoming ) implements Runnable

I then only need to inStream.read() and outStream.write() ??

I still need an very basic skeleton for NIO client, no extras, just very basics,
Port, IP, Socket, what else ??

//----

Thanks,

try this to start with then learn from it…

import java.net.Socket;
import java.net.ServerSocket;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;


public class ChatServer {

   
    private static final int PORT = 9001;
    private static HashSet<String> names = new HashSet<String>();
    private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();

    public static void main(String[] args) throws Exception {

        System.out.println("The chat server is running.");
        ServerSocket listener = new ServerSocket(PORT);

        try {
            while (true) {
                new Handler(listener.accept()).start();
            }
        }

	finally {
            listener.close();
        }
    }

  
    private static class Handler extends Thread {

        private String name;
        private Socket socket;
        private BufferedReader in;
        private PrintWriter out;

        public Handler(Socket socket) {
            this.socket = socket;
        }


        public void run() {

            try {

               
                in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
                out = new PrintWriter(socket.getOutputStream(), true);

                while (true) {
                    out.println("SUBMITNAME");
                    name = in.readLine();
                    if (name == null) {
                        return;
                    }
                    synchronized (names) {
                        if (!names.contains(name)) {
                            names.add(name);
                            break;
                        }
                    }
                }

      
                out.println("NAMEACCEPTED");
                writers.add(out);


                while (true) {
                    String input = in.readLine();
                    if (input == null) {
                        return;
                    }
                    for (Iterator i = writers.iterator(); i.hasNext();) {
                        ((PrintWriter)i.next()).println(
                            "MESSAGE " + name + ": " + input);
                    }
                }
            } catch (IOException e) {
                System.out.println(e);
            } finally {
               
                if (name != null) {
                    names.remove(name);
                }
                if (out != null) {
                    writers.remove(out);
                }
                try {
                    socket.close();
                } catch (IOException e) {
                }
            }
        }
    }
}
/code]

the clientside…


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;


public class ChatClient {

    BufferedReader in;
    PrintWriter out;
    JFrame frame = new JFrame("Chatter");
    JTextField textField = new JTextField(40);
    JTextArea messageArea = new JTextArea(8, 40);

  
    public ChatClient() {

        
        textField.setEditable(false);
        messageArea.setEditable(false);
        frame.getContentPane().add(textField, "North");
        frame.getContentPane().add(new JScrollPane(messageArea), "Center");
        frame.pack();

       
        textField.addActionListener(new ActionListener() {
          
            public void actionPerformed(ActionEvent e) {
                out.println(textField.getText());
                textField.setText("");
            }
        });
    }

   
    private String getServerAddress() {
        return JOptionPane.showInputDialog(
            frame,
            "Enter IP Address of the Server:",
            "Welcome to the Chatter",
            JOptionPane.QUESTION_MESSAGE);
    }

   
    private String getName() {
        return JOptionPane.showInputDialog(
            frame,
            "Choose a screen name:",
            "Screen name selection",
            JOptionPane.PLAIN_MESSAGE);
    }

   
    private void run() throws IOException {

        String serverAddress = getServerAddress();
        Socket socket = new Socket(serverAddress, 9001);
        in = new BufferedReader(new InputStreamReader(
            socket.getInputStream()));
        out = new PrintWriter(socket.getOutputStream(), true);

        
        while (true) {
            String line = in.readLine();
            if (line.startsWith("SUBMITNAME")) {
                out.println(getName());
            } else if (line.startsWith("NAMEACCEPTED")) {
                textField.setEditable(true);
            } else if (line.startsWith("MESSAGE")) {
                messageArea.append(line.substring(8) + "\n");
            }
        }
    }

  
    public static void main(String[] args) throws Exception {
        ChatClient client = new ChatClient();
        client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        client.frame.setVisible(true);
        client.run();
    }
}/code]

Hello!

Thank you very much for the code, still,
im not a professional, im not even well on Java sockets.

Im looking NIO, there is no blocking with NIO code.

Im not sure, but there is not a single .nio library on the code you offered.

I cant my self answer as im so poor with sockets, still, are you sure this is unblocking NIO code ??

I googled “JAVA NIO CLIENTS” and google gave me following, there is two .NIO librarys with the code.
the code i found is a bit too difficult for my level of Java knowledge.

package pkwnet.msgswitch;
 
import java.io.*;
import java.net.*;
import java.util.*;
import java.nio.*;
import java.nio.channels.*;
 
/**
 * a client that sends and receives strings using NIO based socket i/o
 * part of the pkwnet package
 * a very simple text client
 * default command line is java NIOClient -p5050
 * -p port to listen on
 * -i idleTime in seconds
 *
 * @author PKWooster
 * @version 1.0 June 17,2004
 */
public class NIOClient implements Client
{
        static int debugLevel=2;
        private Selector selector;                      // the only selector
        private SelectionKey key;                       // only one key
        private SocketChannel sch;                      // and one channel
        private int bufsz = 8192;
        private int idleTime;
        private String address;
        private int port;
        private ConnectionUser cu;
        private Connection conn;
       	private Timer idleTimer;
        private LinkedList invocations;
        private int state;
        

im looking the very basic skeleton for NIO server + multi client.

//----

Thanks,

Ok first lets do away with a couple of things:

firstly: NIO doesn’t stand for non-blocking input/output it stands for new input/output

NIO can be non-blocking(unblocking doesn’t make much sense but that could just be because your maybe not a native english speaker.) NIO can be blocking all the same.

[quote=“http://java.sun.com/j2se/1.4.2/docs/api/java/nio/channels/SelectableChannel.html”]Blocking mode
A selectable channel is either in blocking mode or in non-blocking mode. In blocking mode, every I/O operation invoked upon the channel will block until it completes. In non-blocking mode an I/O operation will never block and may transfer fewer bytes than were requested or possibly no bytes at all. The blocking mode of a selectable channel may be determined by invoking its isBlocking method.
[/quote]
Which highlights a different thing you should take care of familiarise yourself with the concept of a channel and other things that surround nio, these are a bit awkward. But absolutely make sense in making the stuff happen which we want to make happen. I’m sorry if that last sentence sounds a little ‘un-graspable’, this is because the why behind things that NIO enables you to do, is hard to grasp depending on your background. Have I lost you yet? Either way there are book and blogs which explain this a lot better then me. http://java.sun.com/j2se/1.4.2/docs/guide/nio/ http://www.pdf-search-engine.com/java-nio-pdf.html

As a sidenote NIO2 or NewMore New Input/output is comming soom with 7 I think. http://jcp.org/aboutJava/communityprocess/edr/jsr203/index.html

As for a skeleton of NIO
it’s going to look alike this:


Selector selector = Selector.open();
ServerSocketChannel channel = ServerSocketChannel.open();
configure(channel.socket());  // bind it to an address   
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_ACCEPT);

And then you need a selector.select() loop retrieve the available keys and call stuff like key.isAcceptable() after which you can do something like:
SocketChannel newChannel = server.accept();
and then you have to choose a selector strategy for actual handing connections (handle everything using one selector, use slave selectors and distribute that among threads as you see fit.

take your pointers from, I suppose.
http://weblogs.java.net/blog/jfarcand/archive/2007/05/tricks_and_tips_7.html
http://weblogs.java.net/blog/jfarcand/archive/2006/05/tricks_and_tips_1.html
http://weblogs.java.net/blog/jfarcand/archive/2006/06/tricks_and_tips.html
http://weblogs.java.net/blog/jfarcand/archive/2006/07/tricks_and_tips_3.html
http://weblogs.java.net/blog/jfarcand/archive/2006/07/tricks_and_tips_4.html
http://weblogs.java.net/blog/jfarcand/archive/2006/09/tricks_and_tips_2.html
http://weblogs.java.net/blog/jfarcand/archive/2007/01/tricks_and_tips_5.html

good luck :slight_smile:

http://today.java.net/cs/user/print/a/350 is worth a read too.

There is offcourse also this forum which has nio help tips and ticks all over the place, for example:
http://www.java-gaming.org/index.php/topic,19602.msg155721.html#msg155721

Why not take an existing framework such as Mina or Netty?

One reason might be that they won’t work in the (applet/webstart) sandbox, due to AccessControlExceptions when resolving IP addresses for no reason whatsoever.

Good point!
Are there frameworks that can do this?

* Mr_Light pokes Overkill with http://www.java-gaming.org/index.php/topic,18720.0.html (specifically reply 11 and 12)

My NIO thingy has long been overhauld, and bumped to version 2.

So if you’re interested, let me know and I’ll put up a few more files there.