Java NIO Implementation of the C/S mode multi-person chat tool

Source: Internet
Author: User
Tags set background server port

Little brother to learn NiO, do a console chat tool, do not know how to write code, hope the Great God criticized the guidance.

Server-side, two threads, one processing client request and forwarding message, another processing server administrator directive, on the code:

Package Kindz.onlinechat;import Java.io.ioexception;import Java.net.inetsocketaddress;import Java.net.socketaddress;import Java.nio.bytebuffer;import Java.nio.channels.cancelledkeyexception;import Java.nio.channels.closedchannelexception;import Java.nio.channels.closedselectorexception;import Java.nio.channels.selectionkey;import Java.nio.channels.selector;import Java.nio.channels.ServerSocketChannel; Import Java.nio.channels.socketchannel;import java.util.iterator;import Java.util.linkedlist;import java.util.List Import Java.util.set;public class Server {private static list<socketchannel> clientlist = new LINKEDLIST&LT;SOC Ketchannel> ();//Client list private static Selector Clientmanager = null;//Channel Manager private static Serversocketchannel s erver = null;//Server channel private static Bytebuffer buff = bytebuffer.allocate (1500);//buffer private static int port = 33    33;  public static void Main (string[] args) {if (Args.length > 0) {try {port = integer.parseint (Args[0]);  } catch (NumberFormatException e) {System.out.println ("The port number can only be numeric"); return;    }}try {//initialization failed to exit directly if (!init ()) return; while (Clientmanager.isopen ()) {select ();//Get Ready key list set<selectionkey> keys = Clientmanager.selectedkeys ();//    Traverse the event and process iterator<selectionkey> it = keys.iterator (); while (It.hasnext ()) {Selectionkey key = It.next ();    Determine if key is valid if (!key.isvalid ()) {it.remove ();//to remove continue;    } if (Key.isacceptable ()) {//Request accept (key);    } else if (Key.isreadable ()) {//Has data broadcast (key);    } it.remove ();} }} catch (Closedselectorexception |    Cancelledkeyexception e) {//Must be other thread closed manager} finally {try {if (Clientmanager! = null) clientmanager.close ();    } catch (IOException e) {} try {if (server! = null) server.close ();    } catch (IOException e) {} closeall ();    SYSTEM.OUT.PRINTLN ("Server Stopped");} }//Initialize private static Boolean init () {System.out.println ("Server startup ..."); try {//Get manager Clientmanager = Selecto R. open ();}    catch (IOException e) {System.out.println ("Server failed to start, reason: Channel manager could not get"); return false;} try {//Open Channel Server = Serversocketchannel.open ();} catch (IOException e) {System.out.println ("Server failed to start because: socket    Channel cannot be opened "); return false;} try {//Bind port Server.socket (). bind (New Inetsocketaddress (port)),} catch (IOException e) {System.out.println ("server    Boot failure, Reason: port number not available "); return false;} try {//set to non-blocking mode server.configureblocking (false),} catch (IOException e) {System.out.println ("Server failed to start, cause: Non-blocking mode cut    Failure "); return false;}  try {//register to manager, listen only accept Connection event Server.register (Clientmanager, selectionkey.op_accept);} catch (Closedchannelexception e)    {System.out.println ("Server failed to start because the server channel is down"); return false;} Thread service = new Thread (new Serverservice (Clientmanager));//provide Administrator instruction service thread Service.setdaemon (TRUE);// Set to Background thread Service.start ();    SYSTEM.OUT.PRINTLN ("Server started successfully"); return true; }//wait for event private static void Select () {try {//wait event clientmanager.select ();} catch (IOException e) {//Ignore unknown exception}}//This method gets the requested socket channel and adds it to the list of clients, and of course also registers to manager private static void accept (Se Lectionkey key) {Socketchannel socket = null;try {//accept the requested connection Socket = ((Serversocketchannel) Key.channel ()). Accept ( );} catch (IOException e) {//Connection failed}if (socket = = null) return;    SocketAddress address = null;try {address = socket.getremoteaddress ();    Register socket.configureblocking (FALSE); Socket.register (Clientmanager, selectionkey.op_read);}    catch (Closedchannelexception e) {//Registration failed try {if (socket! = NULL) socket.close (); } catch (IOException E1) {} return;}    catch (IOException e) {try {if (socket! = NULL) socket.close (); } catch (IOException E1) {} return;} Add to the list of clients clientlist.add (socket);    SYSTEM.OUT.PRINTLN ("host" + address + "connect to Server"); }//This method receives data and sends a list of clients for each person private static void broadcast (Selectionkey key) {Socketchannel sender = (socketchannel) k Ey.channel ();//method end does not clean buff.clear (); int status = -1;try {//Read data status = Sender.read (buff);} catch (IOException e) {//unknown IO exception status = 1;}    if (status <= 0) {//abnormally disconnects and removes this client from remove (sender); return;}    Sent to each person for (Socketchannel client:clientlist) {//except his or her own if (client = = sender) Continue;    Buff.flip ();    try {client.write (buff);    } catch (IOException e) {//Send failed, remove this client from remove; }}} private static void Remove (Socketchannel client) {socketaddress address = null;//Storage host addresses information Clientlist.remove (CLI ENT);//Remove the try {address = client.getremoteaddress () from the list,//Get the client address information} catch (IOException E1) {}try {client.close (); /close Connection} catch (IOException E1) {}client.keyfor (Clientmanager). Cancel ();//Anti-registration SYSTEM.OUT.PRINTLN ("Connect with host" + Address + "disconnect"    );     }//Close all channels in the list private static void CloseAll () {for (Socketchannel client:clientlist) {try {if (client! = NULL)    Client.close (); } catch (IOException e) {}}}}
The client is also two threads, one loop waits to receive messages, the other handles user input and sends:

Package Kindz.onlinechat;import Java.io.ioexception;import Java.net.inetaddress;import java.net.InetSocketAddress; Import Java.nio.bytebuffer;import Java.nio.channels.socketchannel;import Java.util.scanner;public class Client    Implements Runnable {private static String IP = null;    private static String name = NULL; private static String serverhost= "127.0.0.1";//server address private static int port=3333;//server port number private static Socketchan Nel socket = null;//with server connection channel public static void Main (string[] args) {if (args.length>0) {if (Args[0].indexof (    ': ') = =-1) {System.err.println ("The destination address is not formatted correctly");    } ServerHost = Args[0].split (":") [0];    try {port = Integer.parseint (Args[0].split (":") [1]);    } catch (NumberFormatException e) {System.err.println ("The port number can only be numeric"); return;    }}try {//initialization failed to exit the program if (!init ()) return; Bytebuffer buff = bytebuffer.allocate (1500);//byte buffer while (Socket.read (buff)! =-1) {//read information String msg = new String (BU Ff.array (), 0, Buff.position ());//Turn into string buff.clear ();//Clean System.out.println (msg);    }} catch (IOException e) {System.out.println ("Disconnect from Server");} finally {close ();    SYSTEM.OUT.PRINTLN ("program has exited");}    }//Input thread @SuppressWarnings ("resource") public void Run () {try {Scanner sc = new Scanner (system.in); The loop waits for input while (Sc.hasnextline ()) {String msg = Sc.nextline (), if (". Exit". Equals (msg)) {Socket.write (Bytebuffer.wra   P ((name+ "-" +ip+ "). GetBytes ()));//Send offline message break;}    msg = name + "-" + IP + ":" + msg;socket.write (Bytebuffer.wrap (Msg.getbytes ()));    }} catch (IOException e) {System.out.println ("Disconnect from Server");} finally {close ();} }//Initialization program private static Boolean init () {System.out.println ("Connecting to Server ..."); try {socket = Socketchannel. Open    (New Inetsocketaddress (ServerHost, Port));//Open channel} catch (IOException e) {System.out.println ("Unable to connect to server"); return false;}  System.out.println ("connected to Server"), try {inetaddress address = inetaddress.getlocalhost ();//Get Native Network information  ip = address.gethostaddress ();//Native IP name = Address.gethostname ();//hostname Socket.write (Bytebuffer.wrap (name+ "-" +i    p+ "on-line"). GetBytes ()));//Send online message} catch (IOException e) {System.out.println ("network exception"); return false;}    Thread thread = new Thread (new Client ()); Thread.setdaemon (true);//Set Background thread Thread.Start (); return true; }//close channel private static void Close () {try {if (socket! = NULL) Socket.close ();} catch (IOException e) {}}}
After writing the feeling is quite simple, but I have been engaged in Java Web Development, exception handling do less, do not know how I deal with this.

Because there are not so many good friends to help test, I also wrote a virtual client to simulate a good base friend:

Package Kindz.onlinechat;import Java.io.ioexception;import Java.net.inetaddress;import java.net.InetSocketAddress; Import Java.nio.bytebuffer;import Java.nio.channels.socketchannel;import Java.util.random;import    Java.util.concurrent.timeunit;public class VClient implements Runnable {private String IP = null;    Private String name = NULL; Private String ServerHost = "127.0.0.1";//server IP address private int port = 3333;//Server port number private Socketchannel socket = null;//and server connection channel private static string[] Msgs = {"Good everyone", "Good Sleepy Ah", "What to Do Today", "I do a lot of this task, first don't talk about", "jquery is the following proto Type followed by a good JavaScript library. It is a lightweight JS library, it is compatible with CSS3, also compatible with various browsers (IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+), jQuery2.0 and subsequent versions will no longer support Ie6/7/8 browser. jquery makes it easier for users to work with HTML (an application under the standard Universal Markup Language), events, animate, and easily provide Ajax interactivity to the site. One of the big advantages of jquery is that its documentation is full, and the various applications are very detailed, as well as a number of mature plugins to choose from. jquery allows the user's HTML page to keep the code and HTML content separate, that is, no more inserting a bunch of JS in the HTML to invoke the command, only need to define the ID can be [8].    "Who has the coffee," "who has time to help me pick up a courier", ". Exit"};    Private random random=new random (); PublIC VClient (String serverhost, int port) {this.serverhost = Serverhost;this.port = port;    public void Run () {try {//Initialize failed exit program if (!init ()) return; Bytebuffer buff = bytebuffer.allocate (1500);//byte buffer while (! Thread.interrupted () &&socket.read (buff)! =-1) {//Read information, interrupt exit String msg = new String (Buff.array (), 0,    Buff.position ());//Turn into string buff.clear ();//Clean System.out.println (msg);    }} catch (IOException e) {System.out.println ("Disconnect from Server");} finally {close ();    SYSTEM.OUT.PRINTLN ("program has exited");} }//Initialization program private Boolean init () {System.out.println ("Connecting to Server ..."); try {socket = Socketchannel. Open (New in    Etsocketaddress (ServerHost, Port));//Open channel} catch (IOException e) {System.out.println ("Cannot connect to server"); return false;} System.out.println ("connected to Server"), try {inetaddress address = inetaddress.getlocalhost ();//Get native network information IP = Address.gethos Taddress ();//Native IP name = Address.gethostname ();//Host name Socket.write (bytebuffer.wrap (name + "-" + IP + "On-line"). GetBytes ());//Send online message} catch (IOException e) {System.out.println ("network exception"); return false;}    Thread thread = new Thread (new Daemon ()),//Private inner class Thread.setdaemon (TRUE);//Set Background thread Thread.Start (); return true; }//Close channel private void close () {try {if (socket! = NULL) Socket.close ();} catch (IOException e) {}}//Private class, daemon thread, output with private classes Daemon implements Runnable {public void run () {try {//auto-loop Send message while (true) {String m sg = Msgs[random.nextint (msgs.length)];//just grab a good message if (". Exit". Equals (msg)) {Socket.write (Bytebuffer.wrap ((name + "-    + IP + "offline"). GetBytes ()));//Send offline information break;    } msg = name + "-" + IP + ":" + msg;    Socket.write (Bytebuffer.wrap (Msg.getbytes ())); TimeUnit.SECONDS.sleep (Random.nextint (9) + 2);//simulate user input process, 2-10 seconds, average 6 seconds to send once}} catch (IOException e) {System.out.println ("    Disconnect from the server ");    } catch (Interruptedexception e) {System.out.println ("Disconnect from server");    } finally {close (); }}    }}
The virtual client is just a thread, and I have a manager for it:

Package Kindz.onlinechat;import Java.util.random;import Java.util.scanner;import Java.util.concurrent.executorservice;import Java.util.concurrent.executors;import Java.util.concurrent.TimeUnit;    public class Vmanager implements Runnable {private static String ServerHost = "127.0.0.1";    private static int port = 3333; private static int num = 3;//Initialize virtual client number private static int min = 5;//Minimum number of virtual clients private static int max = 15;//Max virtual    Number of clients private static random random=new random (); @SuppressWarnings ("resource") public static void main (string[] args) {if (Args.length > 0) {if (Args[0].indexof (    ': ') = =-1) {System.err.println ("The destination address is not formatted correctly");    } ServerHost = Args[0].split (":") [0];    try {port = Integer.parseint (Args[0].split (":") [1]);    } catch (NumberFormatException e) {System.err.println ("The port number can only be numeric"); return;    }}if (Args.length > 1) {try {num = Integer.parseint (args[1]); } catch (NumberFormatException e) {System.err.println ("Number of initialization numbers only"); reTurn    }}if (Args.length > 2) {try {min = Integer.parseint (args[2]);    } catch (NumberFormatException e) {System.err.println ("minimum number can only be numeric"); return;    }}if (Args.length > 3) {try {max = Integer.parseint (args[3]);    } catch (NumberFormatException e) {System.err.println ("Maximum number of digits only");    }}IF (Max < num) {System.err.println ("The number of initializations cannot be greater than maximum"); return;}    if (Max < min) {System.err.println ("minimum quantity cannot be greater than maximum"); return;} Thread manager = new Thread (new Vmanager ()); Manager.start (); Scanner sc = new Scanner (system.in); String arg = null;//instruction while (Sc.hasnextline ()) {arg = Sc.nextline ();//input instruction if ("Shutdown". Equals (Arg)) {MANAGER.I    Nterrupt (); break;    } else {System.out.println ("unknown instruction");  }}} public void Run () {Executorservice manager = Executors.newfixedthreadpool (max);//thread pool Manager//Initialize several client for (int i = 0; i < num; i++) {Manager.execute (new VClient (ServerHost, Port));} try {int interval= (int) (2*48000.0/min) +1;//user line interval time range while (! ThreAd.interrupted ()) {TimeUnit.MILLISECONDS.sleep (Random.nextint (interval));//user will be offline for about 48 seconds, try to keep the minimum number of users Manager.execute    (New VClient (ServerHost, Port));    }} catch (Interruptedexception e) {} finally {System.out.println ("Stopping all Clients ..."); Manager.shutdownnow ();//Interrupt All Clients}}}
Virtual client about average 6 seconds to send a message, the probability of each downline is 1/8, so the virtual client is about 48 seconds on the line will be offline, so want to ensure (only try to guarantee) the minimum number of virtual clients, as long as the 48 seconds to ensure that a fixed number of users online, but here, The frequency of virtual client increases is also random and feels more realistic.

I want to turn the Java bottom job, so in the study hard, hope that the great God can point out the wrong place for the younger brother.

Children's shoes that want to learn Java NiO can also draw on my code.

Willing to fly with the coder on the csdn on the road of technology.

Java NIO Implementation of the C/S mode multi-person chat tool

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.