基于applet与ServerSocket的网络聊天室(记得是上学的时候写的,现在都忘了,记录一下)...

源码下载:下载
http://down.0379zd.com/news/show/9001.htm

chatServer.java

ContractedBlock.gif ExpandedBlockStart.gif Code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.*;

public class chatServer extends JFrame {
  
//以下为图形界面变量
  JPanel contentPane;
  JMenuBar jMenuBar1 
= new JMenuBar();
  JMenu jMenuFile 
= new JMenu();
  JMenuItem jMenuFileExit 
= new JMenuItem();
  JMenu jMenuHelp 
= new JMenu();
  JMenuItem jMenuHelpAbout 
= new JMenuItem();
  JLabel statusBar 
= new JLabel();
  BorderLayout borderLayout1 
= new BorderLayout();
  JPanel jPanel1 
= new JPanel();
  BorderLayout borderLayout2 
= new BorderLayout();
  JLabel jLabel1 
= new JLabel();
  
static java.awt.List jList1 = new java.awt.List(13); 
  JScrollPane scrollpane
=new JScrollPane(jList1);
  
//以下为网络相关变量
  
//用vector向量数组存储连接客户变量
  static Vector clients=new Vector(10);
  
static ServerSocket server=null;//建立服务器socket
  static int active_connects=0;//用来存储目前连接的客户数
  static Socket socket=null;//用来存储一个套接字连接
  
//聊天服务器的main方法
   public static void main(String[] args) {
    
try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    
catch(Exception e) {
      e.printStackTrace();
    }
    chatServer chatServer1
=new chatServer();//实例化一个chatServer类
    chatServer1.show();
    System.out.println(
"正在启动服务器");    
    
try
       {
       
//使用端口2525初始化服务器套接字    
        server=new ServerSocket(2525);
    }
    
catch(IOException e)
       {
        System.out.println(
"Error:"+e);
    }
    
while(true)
       {
       
//当客户数小于5个时开始连接
        if(clients.size()<5)       
           {
            
try
               {
               
//用来存储连接上的客户socket    
                socket=server.accept();   
                
if(socket!=null)
                {
                
//在控制台打印客户连接信息    
                System.out.println(socket+"连接");                                 
             }
            }
            
catch(IOException e)
               {
                System.out.println(
"Error:"+e);
            }
            
int i=0;                        
               
do{                
                
//定义并实例化一个Client线程类,一个就对应一个客户连接
                Client c=new Client(socket);
                clients.addElement(c);
//加入clients数组中
                if(checkName(c))//调用checkName方法验证c的合法性
                   {
                    
//定义connum来存储活动连接数    
                    int connum=++chatServer1.active_connects;
                    
//在状态栏里显示连接数
                    String constr="目前有"+connum+"个客户相连";
                    chatServer1.statusBar.setText(constr);
                    
//将连接客户的socket信息存储进listdata数组
                    Client listdata=(Client)clients.elementAt(i);
                    
//将客户socket信息写入list框
                    chatServer1.jList1.addItem(listdata.ip+"连接",i);  
                    c.start();
//启动线程
                    notifyRoom();//用notifyRoom方法来监视聊天室连接变化
                
//不断改变clients数组并刷新客户端信息                    
                }
                
else
                   {
                    
//如果名字不合法
                    c.ps.println("TAKEN");                    
                    disconnect(c);                    
                }
                i
++;
                
break;                
            }
            
while(i<clients.size());            
        }
        
else//如果clients数组超过了5个
           {
            
try{Thread.sleep(200);}
            
catch(InterruptedException e)
               {
            }
        }
    }
  }
  
//chatServer类的构造函数,用来初始化一些UI信息
  public chatServer()                          
  {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    
try {
      jbInit();
    }
    
catch(Exception e) {
      e.printStackTrace();
    }
  }
  
//初始化组件
  private void jbInit() throws Exception  {
    contentPane 
= (JPanel) this.getContentPane();
    contentPane.setLayout(borderLayout1);
    
this.setSize(new Dimension(400300));
    
this.setTitle("简易聊天服务器端");
    statusBar.setText(
"目前的连接数为:");
    jMenuFile.setText(
"文件");
    jMenuFileExit.setText(
"退出");
    jMenuFileExit.addActionListener(
new ActionListener()  {
      
public void actionPerformed(ActionEvent e) {
        jMenuFileExit_actionPerformed(e);
      }
    });
    jMenuHelp.setText(
"帮助");
    jMenuHelpAbout.setText(
"关于");
    jMenuHelpAbout.addActionListener(
new ActionListener()  {
      
public void actionPerformed(ActionEvent e) {
        jMenuHelpAbout_actionPerformed(e);
      }
    });    
    jPanel1.setLayout(borderLayout2);
    jLabel1.setText(
"服务器端连接的客户:");
    jMenuFile.add(jMenuFileExit);
    jMenuHelp.add(jMenuHelpAbout);
    jMenuBar1.add(jMenuFile);
    jMenuBar1.add(jMenuHelp);
    
this.setJMenuBar(jMenuBar1);
    contentPane.add(statusBar, BorderLayout.SOUTH);
    contentPane.add(jPanel1, BorderLayout.CENTER);
    jPanel1.add(jLabel1,  BorderLayout.NORTH);
    jPanel1.add(scrollpane, BorderLayout.CENTER);    
  }
  
//实现退出菜单方法
  public void jMenuFileExit_actionPerformed(ActionEvent e)   
{
    
//向客户端发送断开连接信息    
    sendClients(new StringBuffer("QUIT"));                   
    closeAll();
//调用closeAll方法关闭所有连接                                               
    System.exit(0);
  }
  
//实现about对话框,意义不大,可以去掉
  public void jMenuHelpAbout_actionPerformed(ActionEvent e)  
  {
    chatServer_AboutBox dlg 
= new chatServer_AboutBox(this);
    Dimension dlgSize 
= dlg.getPreferredSize();
    Dimension frmSize 
= getSize();
    Point loc 
= getLocation();
    dlg.setLocation((frmSize.width 
- dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y);
    dlg.setModal(
true);
    dlg.show();
  }                                
  
//实现关闭服务器程序要进行的操作
  protected void processWindowEvent(WindowEvent e)          
      {
    
super.processWindowEvent(e);
    
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      jMenuFileExit_actionPerformed(
null);
    }
  }
  
/*以下实现各种方法*/
  
//用来监视连接信息,不断刷新clients数组并刷新客户端用户列表信息
  public static void notifyRoom()
    {
     StringBuffer people
=new StringBuffer("PEOPLE");
     
for(int i=0;i<clients.size();i++)
        {
         Client c
=(Client)clients.elementAt(i);
         people.append(
":"+c.name);         
     }
     
//用sendClients方法向客户端发送信息
     sendClients(people);
  }
  
//实现sendClients方法专用来向每个连接的客户端发送信息
  public static synchronized void sendClients(StringBuffer msg)   
    {
     
for(int i=0;i<clients.size();i++)
        {
         Client c
=(Client)clients.elementAt(i);
         c.send(msg);
     }
  }
  
//实现关闭所有连接信息
  public static void closeAll()                             
    {
     
//遍历clients数组删除所有连接客户信息    
     while(clients.size()>0)
        {
         Client c
=(Client)clients.firstElement();
         
try
            {
             c.socket.close();
         }
         
catch(IOException e)
            {
             System.out.println(
"Error:"+e);
         }
         
finally
            {
             clients.removeElement(c);
         }
     }
  }
  
//实现检查连接客户的socket信息是否合法
  public static boolean checkName(Client newclient)         
    {
     
for(int i=0;i<clients.size();i++)
        {
         Client c
=(Client)clients.elementAt(i);
         
if((c!=newclient)&&c.equals(newclient.name))
             
return false;
     }
     
return(true);
  }
  
//实现断开单个客户的方法
  public static synchronized void disconnect(Client c)         
    {
     
try
        {
         
//在服务器端程序的list框中显示断开信息             
         jList1.addItem(c.ip+"断开连接");
         
//将连接数减1
         chatServer.active_connects--;
         
//向客户发送断开连接信息
             c.send(new StringBuffer("退出"));
         c.socket.close();         
     }
     
catch(IOException e)
        {
         System.out.println(
"Error:"+e);
     }
     
finally
        {
         
//从clients数组中删除此客户的相关socket等信息        
         clients.removeElement(c);
     }
  }
}
//实现 Client线程类
class Client extends Thread                              
  {
        Socket socket;
//用来存储一个连接客户的socket信息
    String name;//用来存储客户的连接姓名
    String ip;//用来存储客户的ip信息
     DataInputStream dis;//用来实现接受从客户端发来的数据流
    PrintStream ps;//用来实现向客户端发送信息的打印流
        
//实现想客户端发送信息的方法
    public void send(StringBuffer msg)                   
      {
       ps.println(msg);
//用打印流发送信息
       ps.flush();
    }
        
//Client线程类的构造器
    public  Client(Socket s)                             
      {
       socket
=s;                                           
       
try
          {
           
//存储特定客户socket的输入流接受s这个客户发送到服务器端的信息    
               dis=new DataInputStream(s.getInputStream());
               
//存储特定客户socket的输出流发送服务器给s这个客户的信息  
           ps=new PrintStream(s.getOutputStream());
           
//读取接受来的信息          
           String info=dis.readLine();
           
//用StringTokenizer类来读取用":"分段字符
           StringTokenizer stinfo=new StringTokenizer(info,":"); 
           
//head用来存储类似于关键字的头信息
           String head=stinfo.nextToken();
                   
if(stinfo.hasMoreTokens())
                   
//关键字后的第二段数据是客户名信息           
           name=stinfo.nextToken();
           
if(stinfo.hasMoreTokens())
           
//关键字后的第三段数据是客户ip信息
           ip=stinfo.nextToken();
           
//在控制台打印头信息
           System.out.println(head);
       }
       
catch(IOException e)
          {
           System.out.println(
"Error:"+e);
       }
    }
        
//线程运行方法   
    public void run()                                           
      {
       
while(true)
          {
           String line
=null;
           
try
              {
               
//读取客户端发来的数据流          
               line=dis.readLine();               
           }
           
catch(IOException e)
              {
               System.out.println(
"Error"+e);
               chatServer.disconnect(
this);
               chatServer.notifyRoom();
               
return;
           }
           
if(line==null)//客户已离开
              {
               chatServer.disconnect(
this);
               chatServer.notifyRoom();
               
return;
              }           
           StringTokenizer st
=new StringTokenizer(line,":");
           String keyword
=st.nextToken();
           
//如果关键字是MSG则是客户端发来的聊天信息
           if(keyword.equals("MSG"))
              {
               
//在服务器端再重新建立一个字符缓冲    
                   StringBuffer msg=new StringBuffer("MSG:");
               msg.append(name);
               msg.append(st.nextToken(
"\0"));
               
//再将某个客户发来的聊天信息发送到每个连接客户的聊天栏中
               chatServer.sendClients(msg);
           }
           
//如果关键字是QUIT则是客户端发来断开连接的信息
           else if(keyword.equals("退出"))
              {               
               
//服务器断开与这个客户的连接    
                   chatServer.disconnect(this);
                   
//继续监听聊天室并刷新其他客户的聊天人名list
               chatServer.notifyRoom();
               
this.stop();                                   
           }
       }
    }
  }  
file.java
ContractedBlock.gif ExpandedBlockStart.gif Code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class chatServer_AboutBox extends JDialog implements ActionListener {
  JPanel panel1 
= new JPanel();
  JPanel panel2 
= new JPanel();
  JPanel insetsPanel1 
= new JPanel();
  JPanel insetsPanel2 
= new JPanel();
  JPanel insetsPanel3 
= new JPanel();
  JButton button1 
= new JButton();
  JLabel imageLabel 
= new JLabel();
  JLabel label1 
= new JLabel();
  JLabel label2 
= new JLabel();
  JLabel label3 
= new JLabel();
  JLabel label4 
= new JLabel();
  BorderLayout borderLayout1 
= new BorderLayout();
  BorderLayout borderLayout2 
= new BorderLayout();
  FlowLayout flowLayout1 
= new FlowLayout();
  GridLayout gridLayout1 
= new GridLayout();
  String product 
= "简易聊天服务器端";
  String version 
= "1.0";
  String copyright 
= "Copyright (c) 2002";
  String comments 
= "本聊天室服务器端实现了多线程客户连接和显示连接信息";
  
public chatServer_AboutBox(Frame parent) {
    
super(parent);
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    
try {
      jbInit();
    }
    
catch(Exception e) {
      e.printStackTrace();
    }
    pack();
  }
  
//初始化组件
  private void jbInit() throws Exception  {
    
this.setTitle("关于");
    setResizable(
false);
    panel1.setLayout(borderLayout1);
    panel2.setLayout(borderLayout2);
    insetsPanel1.setLayout(flowLayout1);
    insetsPanel2.setLayout(flowLayout1);
    insetsPanel2.setBorder(BorderFactory.createEmptyBorder(
10101010));
    gridLayout1.setRows(
4);
    gridLayout1.setColumns(
1);
    label1.setText(product);
    label2.setText(version);
    label3.setText(copyright);
    label4.setText(comments);
    insetsPanel3.setLayout(gridLayout1);
    insetsPanel3.setBorder(BorderFactory.createEmptyBorder(
10601010));
    button1.setText(
"确定");
    button1.addActionListener(
this);
    insetsPanel2.add(imageLabel, 
null);
    panel2.add(insetsPanel2, BorderLayout.WEST);
    
this.getContentPane().add(panel1, null);
    insetsPanel3.add(label1, 
null);
    insetsPanel3.add(label2, 
null);
    insetsPanel3.add(label3, 
null);
    insetsPanel3.add(label4, 
null);
    panel2.add(insetsPanel3, BorderLayout.CENTER);
    insetsPanel1.add(button1, 
null);
    panel1.add(insetsPanel1, BorderLayout.SOUTH);
    panel1.add(panel2, BorderLayout.NORTH);
  }
  
//退出窗口
  protected void processWindowEvent(WindowEvent e) {
    
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      cancel();
    }
    
super.processWindowEvent(e);
  }
  
//关闭对话框
  void cancel() {
    dispose();
  }
  
//当单击按钮时,关闭对话框
  public void actionPerformed(ActionEvent e) {
    
if (e.getSource() == button1) {
      cancel();
    }
  }
}
file.java
ContractedBlock.gif ExpandedBlockStart.gif Code
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;
import java.io.*;
import java.util.*;

public class chatApplet extends Applet {
  
/*以下用于定义UI变量*/
  Panel panel1 
= new Panel();//用于放置输入姓名和连接两个按钮
  BorderLayout borderLayout1 = new BorderLayout();
  Panel panel2 
= new Panel();//用于放置聊天信息显示和聊天人员列表
  Panel panel3 = new Panel();//用于放置发送信息区域
  FlowLayout flowLayout1 = new FlowLayout();
  FlowLayout flowLayout2 
= new FlowLayout();
  Label label1 
= new Label();
  TextField name_txt 
= new TextField(15);
  Button button1 
= new Button();
  Button button2 
= new Button();
  TextArea chat_txt 
= new TextArea(15,30);
  Label label2 
= new Label();
  Button button3 
= new Button();
  TextField msg_txt 
= new TextField(20);
  java.awt.List list1 
= new java.awt.List(13);
  
/*以下定义数据流和网络变量*/
  Socket soc
=null;//定义连接套接字
  PrintStream ps=null;//定义打印流 
  Listen listen=null//定义一个客户端线程
  
//初始化图形界面
  public void init()                 
    {
     resize(
475,350);  
     
this.setLayout(borderLayout1);
    panel2.setLayout(flowLayout1);
    panel3.setLayout(flowLayout2);
    label1.setText(
"姓名:");  
    button1.setLabel(
"连接");
    button2.setLabel(
"断开连接");
    chat_txt.setEditable(
false);
    panel2.setBackground(Color.cyan);
    panel1.setBackground(Color.gray);
    label2.setText(
"聊天信息:");
    button3.setLabel(
"发送");
    msg_txt.setText(
"请输入聊天信息");
    panel3.setBackground(Color.gray);
    
this.add(panel1, BorderLayout.NORTH);
    panel1.add(label1, 
null);
    panel1.add(name_txt, 
null);
    panel1.add(button1, 
null);
    panel1.add(button2, 
null);
    
this.add(panel2, BorderLayout.CENTER);
    panel2.add(chat_txt, 
null);
    panel2.add(list1, 
null);
    
this.add(panel3,  BorderLayout.SOUTH);
    panel3.add(label2, 
null);
    panel3.add(msg_txt, 
null);
    panel3.add(button3, 
null);
  }
  
//事件触发代码
  public boolean action(Event evt,Object obj)    
    {
      
if(evt.target instanceof Button)
        {
         String label
=(String) obj;
         
if(label.equals("连接"))//如果点击连接后
            {
             
if(soc==null)
                 {
                 
try
                    {
                    
//使用端口2525实例化一个本地套接字    
                     soc=new Socket(InetAddress.getLocalHost(),2525);     
                     
//在控制台打印实例化的结果
                     System.out.println(soc);                             
                     
//将ps指向soc的输出流
                     ps=new PrintStream(soc.getOutputStream());           
                     
//定义一个字符缓冲存储发送信息
                     StringBuffer info=new StringBuffer("INFO: ");        
                     
//其中INFO为关键字让服务器识别为连接信息
                     
//并将name和ip用":"分开,在服务器端将用一个
                     
//StringTokenizer类来读取数据
                     String userinfo=name_txt.getText()+":"+InetAddress.getLocalHost().toString();
                     ps.println(info.append(userinfo));                
                     ps.flush();
                     
//将客户端线程实例化
                     listen=new Listen(this,name_txt.getText(),soc);      
                     listen.start();
//启动线程
                 }
                 
catch(IOException e)
                    {
                     System.out.println(
"Error:"+e);
                     disconnect();
                 }
             }
         }
       
else if(label.equals("断开连接"))
            {
        
//如果点击断开连接按钮则运行disconnect()        
             disconnect();
       }
       
//如果点击发送按钮
       else if(label.equals("发送"))
            {
             
if(soc!=null)
                {
                 
//定义并实例化一个字符缓冲存储发送的聊天信息        
                 StringBuffer msg=new StringBuffer("MSG: "); 
                     
//其中MSG为关键词
                 try
                 {
                        String msgtxt
=new String(msg_txt.getText());
                 }
                 
catch(Exception e){}                 
                 
//用打印流发送聊天信息
                 ps.println(msg.append(msg_txt.getText()));          
                 ps.flush();
             }
       }
      }
     
return true;
  } 
  
//客户端点击断开连接要运行的方法
  public void disconnect()                                         
    {
     
if(soc!=null)
        {
         
try
            {
                listen.suspend();
                
//用打印流发送QUIT信息通知服务器断开此次通信
            ps.println("QUIT");
            ps.flush();
            soc.close();
//关闭套接字
         }
         
catch(IOException e)
            {
             System.out.println(
"Error:"+e);
         }
         
finally
            {             
         }
     }
  }
 
//客户端线程类用来监听服务器传来的信息
  class Listen extends Thread       
{
 
//用来存储客户端连接后的name信息    
 String name=null;
 
//用来实现客户端接受服务器数据的输入流
 DataInputStream dis=null;          
 
//用来实现从客户端发送数据到服务器的打印流
 PrintStream ps=null;               
 
//用来存储客户端的socket信息
 Socket socket=null;                
 
//用来存储当前运行的chatApplet实例
 chatApplet parent=null;             
 
//Listen类的构造器 
 public Listen(chatApplet p,String n,Socket s)   
    {
     
//接受参数
     parent=p;
     name
=n;
     socket
=s;
     
try
        {
         
//实例化两个数据流
         dis=new DataInputStream(s.getInputStream());
         ps
=new PrintStream(s.getOutputStream());
     }
     
catch(IOException e)
        {
         System.out.println(
"Error:"+e);
         parent.disconnect();
       }
    } 
 
//线程运行方法 
 public void run()                               
    {
      String msg
=null;
      
while(true)
        {
          
//读取从服务器传来的信息        
         try{msg=dis.readLine();}                 
         
catch(IOException e)
            {
             System.out.println(
"Error:"+e);
             parent.disconnect();
         }
         
//如果从服务器传来的信息为空则断开此次连接
         if (msg==null)                           
         {
           parent.listen
=null;              
           parent.soc
=null;
           parent.list1.clear();
           
return;
         }
         
//用StringTokenizer类来实现读取分段字符
         StringTokenizer st=new StringTokenizer(msg,":");   
         
//读取信息头即关键字用来识别是何种信息
         String keyword=st.nextToken();                     
                 
//如果是PEOPLE则是服务器发来的客户连接信息
         if(keyword.equals("PEOPLE"))                      
             
//主要用来刷新客户端的用户列表
            {
             parent.list1.clear();
             
//遍历st取得目前所连接的客户
             while(st.hasMoreTokens())                     
                {
                 String str
=st.nextToken();
                 parent.list1.addItem(str);
             }
         }
         
//如果关键字是MSG则是服务器传来的聊天信息
         else if(keyword.equals("MSG"))                   
                 
//主要用来刷新客户端聊天信息区将每个客户的聊天内容显示出来
            {
             String usr
=st.nextToken();
             parent.chat_txt.appendText(usr);
             parent.chat_txt.appendText(st.nextToken(
"\0"));
             parent.chat_txt.appendText(
"\n\n");
         }
         
//如果关键字是QUIT则是服务器关闭的信息
         else if(keyword.equals("QUIT"))
         
//用来切断此次连接
            {
             System.out.println(
"Quit");
             
try
             {parent.listen.stop();
              parent.listen
=null;
              parent.soc.close();
              parent.soc
=null;
             }
catch(IOException e)
             {
                 System.out.println(
"Error:"+e);
                 }
              parent.list1.clear();             
             
return;
         }
      }
 }  

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值