Program: Chat Client

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.

Chat client in action

Figure 15-2. Chat client in action

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);
    }
}

See Also

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.60.63