基于GUI的简单聊天室02

服务器端

与上一篇相比,加进了线程内部类,解决多个客户端连接时,服务器无法全部响应的问题。

利用List集合来装载客户端的对象。

还需要注意全局变量的应用。

 

  1 /**
  2  * 相比01,加进了线程内部类,解决多个客户端连接时,服务器无法全部响应的问题。
  3  * @author Administrator
  4  *
  5  */
  6 
  7 import java.io.DataInputStream;
  8 import java.io.DataOutputStream;
  9 import java.io.EOFException;
 10 import java.io.IOException;
 11 import java.net.BindException;
 12 import java.net.ServerSocket;
 13 import java.net.Socket;
 14 import java.util.ArrayList;
 15 import java.util.List;
 16 
 17 public class ChatSever02 {
 18     // 布尔类型变量表示服务器是否开着
 19     boolean started = false;
 20     
 21     ServerSocket ss = null;
 22 
 23     List<Client> clients  = new ArrayList<Client>();
 24     
 25     public static void main(String[] args) {
 26             new ChatSever02().start();
 27     }
 28     
 29     public void start() {
 30         try {
 31             // 建立服务端,8888为端口号
 32             ss = new ServerSocket(8888);
 33             started = true;
 34         } 
 35         catch (BindException e) {
 36             System.out.println("Socket has been used !");
 37             System.out.println("请重启服务器 !");
 38             System.exit(0);
 39         }catch (IOException e) {
 40             e.printStackTrace();
 41         }
 42         // 服务器开启后,started变为true
 43         try {
 44             // 接受客户端的连接
 45             while (started) {
 46                 Socket s = ss.accept();
 47                 //构造Client对象
 48                 Client c = new Client(s);
 49                 clients.add(c);
 50                 System.out.println("一个客户连接");
 51                 //启动线程
 52                 new Thread(c).start();
 53             }
 54         }  catch (Exception e) {
 55              e.printStackTrace();
 56         } finally {
 57                 try {
 58                     ss.close();
 59                 } catch (IOException e) {
 60                     e.printStackTrace();
 61                 }
 62         }
 63     }
 64     
 65 
 66     /**
 67      * 建立线程内部类
 68      */
 69     class Client implements Runnable{
 70         
 71         //要保有自己的Socket属性
 72         private Socket s = null;
 73         
 74         //自己的数据输入流
 75         private DataInputStream dis = null;
 76         
 77         private DataOutputStream dos = null;
 78         
 79         private boolean bConnected = false ;
 80         
 81         //采用构造方法,把Socket属性传进来
 82         public Client(Socket s) {
 83             //赋值给s 
 84             this.s = s ;
 85             //将dis初始化
 86             try {
 87                 dis = new DataInputStream(s.getInputStream());
 88                 dos = new DataOutputStream(s.getOutputStream());
 89                 //连接成功后,bConnected 变为true
 90                 bConnected = true ;
 91             } catch (IOException e) {
 92                 e.printStackTrace();
 93             }
 94         }
 95         
 96         /**
 97          * 发送信息的方法
 98          */
 99         public void send(String str) {
100             try {
101                 dos.writeUTF(str);
102 System.out.println(str);
103             } catch (IOException e) {
104                 e.printStackTrace();
105             }
106         }
107         @Override
108         public void run() {
109                 try {
110                     //while循环范围过大, 导致过一直报错;
111                     while (bConnected) {
112                         String str = dis.readUTF ();
113 //System.out.println(str);
114                         //发送信息
115                         for(int i = 0;i < clients.size(); i++) {
116                             Client c = clients.get(i);
117                             c.send(str);
118 //System.out.println(str);
119                         }
120                         
121                         /*利用迭代器
122                         for(Iterator it = clients.iterator();it.hasNext();) {
123                             Client c = it.next();
124                             c.send(str);
125                         }
126                         */
127                         /*利用迭代器第二版本
128                         Iterator<Client> it = clients.iterator();
129                         while(it.hasNext()) {
130                             Client c = it.next();
131                             c.send(str);
132                         }
133                         */
134                     } 
135                 }catch (EOFException e) {
136                 
137                     System.out.println("Client Close !");
138                 }catch (IOException e) {
139                     e.printStackTrace();
140                 }finally {
141                         try {
142                             if(dis != null) dis.close(); //再设置dis = null;
143                             if(dos != null) dis.close();
144                             if(s != null) s.close();
145                         } catch (IOException e) {
146                             e.printStackTrace();
147                         }
148                 }
149             
150         }
151     }
152 }

 

客户端也只是多了线程类来接收信息

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 * 完成图形界面
 * @author Administrator
 *
 */
public class ChatClient extends JFrame{
    JTextField jTextField = new JTextField();
    
    JTextArea jTextArea = new JTextArea();
    
    Socket s;
    //表示是否连上
    private boolean bConnected = false;
    
    DataOutputStream dos;
    
    DataInputStream dis = null;
    
    public static void main(String[] args) {
        new ChatClient().launchFrame();
    }
    
    public void launchFrame() {
        setLocation(200, 150);
        this.setSize(450, 450);
        this.add(jTextArea,BorderLayout.NORTH);
        this.add(jTextField,BorderLayout.SOUTH);
        jTextField.addActionListener(new TFListener());
        //pack();
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent arg0) {
                disConnect();
                System.exit(0);
            }
        });;
        
        setVisible(true);
        connect();
        new Thread(new RecvThread()).start();
    }
    
    /**
     * 建立连接的方法
     * @throws IOException 
     * @throws UnknownHostException 
     */
    public void connect() {
         try {
            s = new Socket("127.0.0.1",8888);
            //连接好后初始化
            dos = new DataOutputStream(s.getOutputStream());
            dis = new DataInputStream(s.getInputStream());
System.out.println("连接成功");
            bConnected = true;
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 断开连接,关闭资源的方法
     */
    public void disConnect() {
        try {
            dos.close();
            dis.close();
            s.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        
    }
    
    /**
     * 内部类,实现监听
     * 将文本框中的输入打印到文本域中
     *
     */
    
    private class TFListener implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            String content = jTextField.getText().trim();
            //jTextArea.setText(content);
            jTextField.setText("");
            //将文本发送到服务器
            try {
//System.out.println(s);
System.out.println(content);
                dos.writeUTF(content);
                dos.flush();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        
    }

    /**
     * 线程类,用于接受信息
     *
     */
    private class RecvThread implements Runnable{
        
        @Override
        public void run() {
                try {
                    while(bConnected) {
                        String str = dis.readUTF();
//System.out.println(str);
                        jTextArea.setText(jTextArea.getText() + str +"   ");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }        
    }
}

 

posted @ 2019-04-25 00:04  朱健栋  阅读(362)  评论(0编辑  收藏  举报