實時羣聊小程序開發記錄

昨天回憶了一下以前做的一個實時的羣聊小程序。用JAVA寫得。開發步驟如下:

這是面向過程的開發。

第一步,建立服務器端。

第二步,建立客戶端並連接服務端。

第三步,客戶端發送消息服務器端能接收到。

第四步,實現多客戶連接服務端,並能接收多客戶端發來的消息。可以採用多線程和異步的方法解決服務端被佔用的情況。

第五步,服務端轉發客戶端發送的信息到每一個客戶端。

第六步,消除小Bug。

ChatServer.java

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.util.*;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
public class ChatServer
{
    boolean started = false;
    ServerSocket ss = null;
                          
    List<Client> clients = new ArrayList<Client>();
                          
                          
    public static void main(String[] args)
    {
        new ChatServer().start();   
    }
    public void start(){
        try
        {
            ss = new ServerSocket(8881);
        }
        catch (BindException e){
            System.out.println("端口已被佔用!");
            System.out.println("請結束相關進程!");
            System.exit(0);
        }
        catch (Exception e) {
                                  
            e.printStackTrace();
        }
        try{
            started = true;
            while (started)
            {
                Socket s = ss.accept(); //阻塞性函數,不斷接收客戶端連接
                Client c = new Client(s);//不能再靜態main()裏面new一個動態的方法,故將啓動過程包裝成一個public函數
System.out.println("a client connected");
                new Thread(c).start();
                clients.add(c);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }finally{
            try
            {
                ss.close();
            } catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
                              
    }
                          
    class Client implements Runnable{//區分客戶端,用一個線程操作一個客戶端,也可以採用異步的方法。這裏用線程,比較佔資源。等我寫出異步的方法後再共享。
        private Socket s= null;
        private DataInputStream dis= null;
        private DataOutputStream dos=null;
        private boolean bConnected = false;
        public Client(Socket s){
            this.s= s;
            try
            {
                dis=new DataInputStream(s.getInputStream());
                dos=new DataOutputStream(s.getOutputStream());
                bConnected = true;
            } catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
                                  
        }
                              
        public void send(String str){       //
            try
            {
                dos.writeUTF(str);
            } catch (IOException e)
            {
                // TODO Auto-generated catch block
                clients.remove(this);
                System.out.println("一個客戶退出了!List已去除");
                //e.printStackTrace();
            }
        }
                              
        public void run()
        {
            try
            {
                while (bConnected)
                {
                    String str;
                    str = dis.readUTF();// 阻塞性函數,會一直佔用線程資源
System.out.println(str);
                    for (int i = 0; i < clients.size(); i++)
                    {
                        Client c = clients.get(i);
                        c.send(str);
                    }
                }
            }
            catch (EOFException e){
                System.out.println("一個客戶已退出!");
            }catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                if(dis!=null)
                    try
                    {
                        dis.close();
                        if (dos != null)
                            dos.close();
                        if (s != null)
                            s.close();
                    } catch (SocketException e)
                    {
                            clients.remove(this);
                            System.out.println("一個客戶已退出!");
                    }
                    catch (IOException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                                      
            }
        }
    }
}

ChatClient.java

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.TextField;
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.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
                                      
public class ChatClient extends Frame
{
    Socket s = null;
    DataOutputStream dos = null;
    DataInputStream dis = null;
    private boolean bConnected=false;
    TextField tfTxt = new TextField();//輸入框
    TextArea taContent = new TextArea();//顯示聊天信息框
                                         
                                         
    public static void main(String[] args)
    {
        new ChatClient().lanunchFrame();
    }
                                         
    public void lanunchFrame(){
        setLocation(400,300);
        this.setSize(300, 300);
        add(tfTxt,BorderLayout.SOUTH);
        add(taContent,BorderLayout.NORTH);
        pack();//調整空隙
        this.addWindowListener(new WindowAdapter(){
            @Override
            public void windowClosing(WindowEvent e)
            {
                disconnect();
                System.exit(0);
            }
        });
        tfTxt.addActionListener(new TexFileListener());
        setVisible(true);
        connect();
                                             
        new Thread(new RecvThread()).start();
    }
                                         
    public void connect(){
        try
        {
            s= new Socket("127.0.0.1",8881);
            dos=new DataOutputStream(s.getOutputStream());
            dis=new DataInputStream(s.getInputStream());
System.out.println("connected!");
            bConnected =true;
                                                 
        } catch (UnknownHostException e)
        {
            e.printStackTrace();
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }
                                         
    public void disconnect()
    {
        try
        {
            dos.close();
            dis.close();
            s.close();
        } catch (Exception e1)
        {
            e1.printStackTrace();
        }
        /*try
        {
            bConnected = false;  //保證
            recvThread.join();
        }
        catch (InterruptedException e){
            e.printStackTrace();
        }
        finally{
            try
            {
                dos.close();
                dis.close();
                s.close();
            } catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
*/
    }
                                         
    private class TexFileListener implements ActionListener{
        public void actionPerformed(ActionEvent e)
        {
            String str=tfTxt.getText().trim();
            //taContent.setText(str);
            tfTxt.setText("");
            try
            {
                dos.writeUTF(str);
                dos.flush();
                //dos.close();
            } catch (IOException e1)
            {
                e1.printStackTrace();
            }
                                                 
        }
    }
    private class RecvThread implements Runnable{
        public void run()
        {
            try
            {
                while (bConnected)
                {
                    String str = dis.readUTF();
                    //System.out.println(str);
                    taContent.setText(taContent.getText()+str+'\n');
                }
            }
            catch (SocketException e){
                System.out.println("已退出!");
            }
            catch (EOFException e){
                System.out.println("已退出!");
            }
            catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章