服务器端:

//package chapter1;

import java.net.*;

import java.io.*;

import java.util.*;

public class ChatServer { /**

  * @param args

  * m_threads是一个Vector静态变量,维护所有Server方的ServerThread对象,

  * 通过该变量能向所有加入聊天室的聊天者ChatApplet广播信息,撤销退出的聊天者。

  * 聊天服务者ChatServer的主方法。该方法监听聊天者Chat Applet的请求,

  * 并为新连接的聊天者创建一个服务线程。

  */

 public static void main(String[] args) {

  // TODO Auto-generated method stub

         ServerSocket socket=null;

         Vector m_threads=new Vector();

         System.out.println("listen...");

         try

         {

          //设置ServerSocket监听端口号为5555,这个数字必须和程序聊天者ChatApplet中的port参数一致

          socket=new ServerSocket(5555);

         }

         catch(Exception e)

         {

          System.out.println("new ServerSocket() failed!");

          return;

         }

         try

         {

          int nid=0;

          while(true)

          {

           //监听是否有新聊天者Chat Applet连接到聊天Server,

           //线程运行到该语句会封锁,直到有新的连接产生

           Socket s=socket.accept();

           System.out.println("accepted");

           //创建一个新的ServerThread

           ServerThread st=new ServerThread(s,m_threads);

           //为该线程设置一个ID号

           st.setID(nid++);

           //将线程加入到m_threads Vector中

           m_threads.addElement(st);

           //启动服务线程

           new Thread(st).start();

           //通知所有ChatApplet有一个新的网友加入

           for(int i=0;i<m_threads.size();i++)

           {

            ServerThread st1=(ServerThread)m_threads.elementAt(i);

            st1.write("<#>welcome"+st.getID()+"to enter chatroom!");

           }

           System.out.println("Listen again...");

          }

         }

         catch(Exception e)

         {

          System.out.println("Server is down...");

         }

 }}
//监听线程,监听对应的Chat Applet是否有信息传来
class ServerThread implements Runnable

{

 Vector m_threads;

 Socket m_socket=null;

 DataInputStream m_in=null;

 DataOutputStream m_out=null;

 int m_nid;

 //初始化线程

 public ServerThread(Socket s,Vector threads)

 {

  m_socket=s;

  m_threads=threads;

  try

  {

   //构造数据输入、输出流对象

   m_in=new DataInputStream(m_socket.getInputStream());

   m_out=new DataOutputStream(m_socket.getOutputStream());

  }

  catch(Exception e)

  {

  }

 }

 public void run()  //线程的执行体

 {

  System.out.println("thread is running");

  try

  {

   while(true)

   {

    //监听对应的ChatApplet是否传来消息

    //线程封锁在m_in.readUTF()中,直到有信息传来才返回

    String s=m_in.readUTF();

    if(s==null)break;

    //如果Chat Applet传来的信息为“leave”,则通知所有其他的ChatApplet自己推出了

    if(s.trim().equals("leave"))

     for(int i=0;i<m_threads.size();i++)

     {

      ServerThread st=(ServerThread)m_threads.elementAt(i);

      st.write("***"+getID()+"leave..."+"***");

     }

    else

     //向所有ChatApplet广播该消息

    for(int i=0;i<m_threads.size();i++)

    {

     ServerThread st=(ServerThread)m_threads.elementAt(i);

     st.write("<"+getID()+">"+s);

    }

   }

  }

  catch(Exception e)

  {

   e.printStackTrace();

  }

  //从m_threads Vector中删除该线程,表示该线程已经离开聊天室

  m_threads.removeElement(this);

  try

  {

   m_socket.close();

  }

  catch(Exception e)

  { 

     }

 }

 //将msg送回对应的Applet

 public void write(String msg)

 {

  synchronized(msg)

  {

   try

   {

    m_out.writeUTF(msg);

   }

   catch(IOException e){}

  }

 }

 public int getID()  //获得该线程的ID

 {

  return m_nid;

 }

 public void setID(int nid)  //设置线程的ID

 {

  m_nid=nid;

 }

} 
客户端:
//package chapter1;

import java.awt.*;

import java.applet.*;

import java.io.*;

import java.net.*;

//继承Applet,实现Runnable

public class ChatApplet1 extends Applet implements Runnable{

 TextArea m_textarea;     //接受消息显示窗口

 TextField m_textfield;   //发送消息输入窗口

 DataInputStream m_in;    //消息输入流

 DataOutputStream m_out;  //消息输出流 /**

  * @param args  ChatApplet的初始化方法

  */

 public void init()

 {

  //创建窗口

  setLayout(null);

  setSize(426,266);

  m_textarea=new TextArea(10,10);

  m_textfield=new TextField();

  m_in=null;

  m_out=null;

  //初始化Appleton,并连接到聊天服务者

  try

  {

   //获取applet的URL,即通过服务器地址

   URL url=getCodeBase();

   //获取服务器IP地址

   InetAddress inetaddr=InetAddress.getByName(url.getHost());

   Socket m_socket;

   //屏幕显示服务器IP地址、通信协议

   System.out.println("Server:"+inetaddr+""+url.getHost()+""+url.getProtocol());

   //创建与服务器IP地址连接的套接口,5555是聊天服务器套接口端口

   m_socket=new Socket(inetaddr,5555);

   //在套接口上建立输入流

   m_in=new DataInputStream(m_socket.getInputStream());

   //在套接口上建立输出流

   m_out=new DataOutputStream(m_socket.getOutputStream());

  }

  catch(Exception e)

  {

   System.out.println("Error:"+e);

  }

  setLayout(new BorderLayout());

  add("Center",m_textarea);

  add("South",m_textfield);

  m_textarea.setEditable(false);

  //启动监听线程

  new Thread(this).start();

 }

 

 //当聊天者在消息输入窗口键入回车后,读取字符串,发送给聊天服务者。

 

 public boolean handleEvent(Event event)

 {

  String b=m_textfield.getText();

  if((event.target==m_textfield)&&(event.id==Event.ACTION_EVENT))

  {

   m_textfield.setText("");

   //将聊天者输入的消息发送给ChatServer

   try

   {

    m_out.writeUTF(b);   //向聊天服务者发送一个UFT格式字符串

   }

   catch(IOException e){}

   return true;

  }

  else

   return super.handleEvent(event);

 }

 

 //聊天者监听对应的服务线程,在读取对应服务线程传来的消息,并显示在通信显示窗口中

 

 public void run()

 {

  try

  {

   while(true)

   {

    //聊天者监听对应服务线程发来的消息,它将封锁在该语句中,直到消息到来

    String s=m_in.readUTF();   //读一个UTF格式字符串

    if(s!=null)

     //将消息显示在信息显示窗口中

     m_textarea.append(s+"\n");

   }

  }

  catch(Exception e)

  {

   m_textarea.append("Network problem or Server down.\n");

   m_textfield.setVisible(false);

  }

 }

 public void stop()

 {

  try

  {

   m_out.writeUTF("leave");

  }

  catch(IOException e){}

 }

 public static void main(String[] args) {

  // TODO 自动生成方法存根 }
}