要做就做最好的!

Everything is possible!
Java网络聊天室程序

 

服务器端:

//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 自动生成方法存根

 }

}

posted on 2008-12-21 15:05  顒琰  阅读(3012)  评论(0编辑  收藏  举报