| |||||||||||
| |||||||||||
A multithreaded server in Java
Java is a great language for network programming, and for handling applications where you want to do several things at the same time. This article shows you how we've used Java to provide a simple "chatroom" facility on our local area network - all controlled by a daemon process written in Java. Users who want to visit the chatroom can simply telnet to port 1357 on the computer that's running the daemon, and then whatever they type in will be copied to everyone else who's logged in. The daemon will work just as well over a wide area; indeed, if you want to try it out, it's usually running on chat.wellho.net on the internet! THE BASIC PLAN Planning your application is vital in any object oriented language such as Java - for smaller applications you may choose to use informal methods, but for larger applications you'll need something more formal such as UML, and perhaps even tools such as Rational Rose to manage your model. Informally, our plans for the talker are as follows: * A single parent thread will await new connections, and will create a new child thread when it receives a connection * A child thread will exist for each live connection; it will wait for input from the user of the connection, and when input is received it will echo it to all live users. * Threads will be managed in a Vector from which they will be deleted when the connection is closed * A few special directives (such as ".q" to quit) will be provided by the application to allow users to log out, and to enquire as to who is logged on. Have a look through our Java code - see if you can work out how the elements fit together. import java.net.*; import java.io.*; import java.util.*; public class talker implements Runnable { // A simple talker - Sample written by Graham Ellis, April 2001 // No login needed. Connect on port 1357. // commands: // .q quit // .w who // Variables for each thread Socket linkto; // the socket PrintWriter out; // the output and input streams BufferedReader in; int id; // i.d. of the connection String from_name; // name of host connecting // Class Variables static Vector connectiontable; // current connections static int nextid = 1; // Increasing i.d. /////////////////////////////// Main method //////////////////////// public static void main(String [] args) { // Parent thread - create a server socket and await a connection ServerSocket ss = null; Socket s = null; connectiontable = new Vector(); try { ss = new ServerSocket(1357); while ((s=ss.accept())!= null) { // Connection received - create a thread talker now; Thread current = new Thread(now = new talker(s)); current.setDaemon(true); connectiontable.addElement(now); // Save talker into vector .. current.start(); // start the user's thread } } catch (Exception e) { System.out.println(e); } // should add finally block to close down } ///////////////// Constructor for a new thread ////////////////////// talker (Socket from) { id = nextid++; linkto = from; InetAddress source = linkto.getInetAddress(); from_name = source.getHostName(); try { out = new PrintWriter(new OutputStreamWriter (linkto.getOutputStream())); in = new BufferedReader(new InputStreamReader (linkto.getInputStream())); } catch (Exception e) {} } public void run () { String line = " [User has just logged in] "; while (true) { boolean done=false; // read a line from the user if (line == null) { try { out.print(">: "); //prompt,flush,read out.flush(); line = in.readLine(); } catch (Exception e) { System.out.println(e); done = true; // force exit if there's a problem } } // Handle special cases - user input starts with "." if (line.startsWith(".q")) done = true; if (line.startsWith(".w")) { // build up list of host names int k; StringBuffer fred = new StringBuffer("WHO HERE?\n"); for (k=0;k<connectiontable.size();k++) { talker person = (talker)connectiontable.elementAt(k); fred.append(person.from_name); fred.append(" "); } line = fred.toString(); } // echo the line (with a header) to all users String outline = from_name+" "+id+": "+line; int k; for (k=0;k<connectiontable.size();k++) { talker person = (talker)connectiontable.elementAt(k); person.out.println(outline); person.out.flush(); // Vital - ensure it is sent! } // clear out the user if they're done if (done) { connectiontable.removeElement(this); try { out.close(); // closes needed to terminate connection in.close(); // otherwise user's window goes mute linkto.close(); } catch (Exception e) {} break; } line = null; } } } See also Training exercise - a talk server and client in Java Please note that articles in this section of our
web site were current and correct to the best of our ability when published,
but by the nature of our business may go out of date quite quickly. The
quoting of a price, contract term or any other information in this area of
our website is NOT an offer to supply now on those terms - please check
back via our main web site
Related Material
Java - Putting it all together resource index - Java Solutions centre home page You'll find shorter technical items at The Horse's Mouth and delegate's questions answered at the Opentalk forum. At Well House Consultants, we provide training courses on subjects such as Ruby, Perl, Python, Linux, C, C++, Tcl/Tk, Tomcat, PHP and MySQL. We're asked (and answer) many questions, and answers to those which are of general interest are published in this area of our site. | |||||||||||
PH: 0800 043 8225 or 01225 708225 • FAX: 0845 8382 405 or 01225 707126 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho | |||||||||||