This program is a
simple
Chat program. You can’t break in on ICQ or AIM with it, because
they each use their own protocol;[36]
this one simply writes to and reads from a server, locating the
server with the applet method getCodeBase( )
. The
server for this will be presented in Chapter 16.
How does it look when you run it? Figure 15-2 shows me chatting all
by myself one day.
The code is reasonably self-explanatory. We read from the remote server in a thread to make the input and the output run without blocking each other; this is discussed in Chapter 24. The reading and writing are discussed in this chapter. The program is an applet (see Section 17.3) and is shown in Example 15-11.
Example 15-11. ChatClient.java
import java.applet.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; /** Simple Chat Room Applet. * Writing a Chat Room seems to be one of many obligatory rites (or wrongs) * of passage for Java experts these days. * <P> * This one is a toy because it doesn't implement much of a command protocol, which * means we can't query the server as to * who's logged in, * or anything fancy like that. However, it works OK for small groups. * <P> * Uses client socket w/ two Threads (main and one constructed), * one for reading and one for writing. * <P> * Server multiplexes messages back to all clients. * <P> * TODO in V2: use Java's MultiCastSocket, if it works OK on '95. */ public class ChatRoom extends Applet { /** The state */ protected boolean loggedIn; /* The Frame, for a pop-up, durable Chat Room. */ protected Frame cp; /** The default port number */ protected static int PORTNUM = 7777; /** The actual port number */ protected int port; /** The network socket */ protected Socket sock; /** BufferedReader for reading from socket */ protected BufferedReader is; /** PrintWriter for sending lines on socket */ protected PrintWriter pw; /** TextField for input */ protected TextField tf; /** TextArea to display conversations */ protected TextArea ta; /** The Login button */ protected Button lib; /** The LogOUT button */ protected Button lob; /** The TitleBar title */ final static String TITLE = "Chat: Ian Darwin's Toy Chat Room Applet"; /** The message that we paint */ protected String paintMessage; /** Init, inherited from Applet */ public void init( ) { paintMessage = "Creating Window for Chat"; repaint( ); cp = new Frame(TITLE); cp.setLayout(new BorderLayout( )); String portNum = getParameter("port"); port = PORTNUM; if (portNum == null) port = Integer.parseInt(portNum); // The GUI ta = new TextArea(14, 80); ta.setEditable(false); // readonly ta.setFont(new Font("Monospaced", Font.PLAIN, 11)); cp.add(BorderLayout.NORTH, ta); Panel p = new Panel( ); Button b; // The login button p.add(lib = new Button("Login")); lib.setEnabled(true); lib.requestFocus( ); lib.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent e) { login( ); lib.setEnabled(false); lob.setEnabled(true); tf.requestFocus( ); // set keyboard focus in right place! } }); // The logout button p.add(lob = new Button("Logout")); lob.setEnabled(false); lob.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent e) { logout( ); lib.setEnabled(true); lob.setEnabled(false); lib.requestFocus( ); } }); p.add(new Label("Message here:")); tf = new TextField(40); tf.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent e) { if (loggedIn) { pw.println(Chat.CMD_BCAST+tf.getText( )); tf.setText(""); } } }); p.add(tf); cp.add(BorderLayout.SOUTH, p); cp.addWindowListener(new WindowAdapter( ) { public void windowClosing(WindowEvent e) { // If we do setVisible and dispose, then the Close completes ChatRoom.this.cp.setVisible(false); ChatRoom.this.cp.dispose( ); logout( ); } }); cp.pack( ); // After packing the Frame, centre it on the screen. Dimension us = cp.getSize( ), them = Toolkit.getDefaultToolkit().getScreenSize( ); int newX = (them.width - us.width) / 2; int newY = (them.height- us.height)/ 2; cp.setLocation(newX, newY); cp.setVisible(true); paintMessage = "Window should now be visible"; repaint( ); } /** LOG ME IN TO THE CHAT */ public void login( ) { if (loggedIn) return; try { sock = new Socket(getCodeBase().getHost( ), port); is = new BufferedReader(new InputStreamReader(sock.getInputStream( ))); pw = new PrintWriter(sock.getOutputStream( ), true); } catch(IOException e) { showStatus("Can't get socket: " + e); cp.add(new Label("Can't get socket: " + e)); return; } // construct and start the reader: from server to textarea // make a Thread to avoid lockups. new Thread(new Runnable( ) { public void run( ) { String line; try { while (loggedIn && ((line = is.readLine( )) != null)) ta.append(line + " "); } catch(IOException e) { showStatus("GAA! LOST THE LINK!!"); return; } } }).start( ); // FAKE LOGIN FOR NOW pw.println(Chat.CMD_LOGIN + "AppletUser"); loggedIn = true; } /** Log me out, Scotty, there's no intelligent life here! */ public void logout( ) { if (!loggedIn) return; loggedIn = false; try { if (sock != null) sock.close( ); } catch (IOException ign) { // so what? } } // It is deliberate that there is no STOP method - we want to keep // going even if the user moves the browser to another page. // Anti-social? Maybe, but you can use the CLOSE button to kill // the Frame, or you can exit the Browser. /** Paint paints the small window that appears in the HTML, * telling the user to look elsewhere! */ public void paint(Graphics g) { Dimension d = getSize( ); int h = d.height; int w = d.width; g.fillRect(0, 0, w, 0); g.setColor(Color.black); g.drawString(paintMessage, 10, (h/2)-5); } }
This chat applet might not work on all browser flavors; you might need the Java Plug-in. See Section 23.6.
There are many better-structured ways to write a chat client, including RMI, Java’s Remote Methods Interface (see Section 22.1) and the Java Messaging Services, part of the Java 2 Enterprise Edition.
If you need to encrypt your socket connection, check out Sun’s JSSE (Java Secure Socket Extension).
For a good overview of network programming from the C programmer’s point of view, see the book Unix Network Programming by the late W. Richard Stevens. Despite the book’s name, it’s really about socket and TCP/IP/UDP programming, and covers all parts of the (Unix version) networking API and protocols such as TFTP in amazing detail.
[36] For an open source program that “AIMs” to let you talk to both from the same program, check out Jabber, at http://www.jabber.org.
3.147.60.63