java線上聊天系統

sd訫訴sd發表於2018-01-28

java線上聊天系統

本部落格是博主在觀看相關視訊後寫下的程式碼,希望能夠幫助大家掌握java socket的相關知識。

  • 原理介紹
  • 程式碼展示

原理介紹

一、搭建伺服器端
a)、建立ServerSocket物件繫結監聽埠。
b)、通過accept()方法監聽客戶端的請求。
c)、建立連線後,通過輸入輸出流讀取客戶端傳送的請求資訊。
d)、通過輸出流向客戶端傳送請求資訊。
e)、關閉相關資源。

二、搭建客戶器端
a)、建立Socket物件,指明需要連線的伺服器的地址和埠。
b)、建立連線後,通過輸出流向伺服器傳送請求資訊。
c)、通過輸入流獲取伺服器的響應資訊。
d)、關閉響應資源

程式碼展示

伺服器端程式碼:


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;

/**
 * 版本三:轉發給其他的客戶端 1.儲存每一個客戶端的連線
 *
 */
public class ChatSeverEdition3 {
    // 伺服器端是否啟動
    boolean started = false;
    ServerSocket serverSocket = null;
    ArrayList<Client> clients = new ArrayList<Client>();

    public static void main(String[] args) {

        new ChatSeverEdition3().start();
    }

    public void start() {

        try {
            serverSocket = new ServerSocket(8888);
            started = true;
        } catch (BindException e) {
            // 多次啟動伺服器
            System.out.println("埠使用中。。。。");
            System.out.println("請關掉相關程式,並重新執行伺服器!");
            System.exit(0);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {

            while (started) {
                // 客戶端是否連線
                Socket socket = serverSocket.accept();
                // main()方法是static方法,不能在其中new動態類Client
                Client client = new Client(socket);
                // 執行緒啟動
                new Thread(client).start();
                // 將當前啟動的客戶端儲存下來
                clients.add(client);
                System.out.println("new Client成功!");
                System.out.println("A Client connected!");


            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 
     * 
     *
     */
    class Client implements Runnable {
        private Socket s;
        private DataInputStream dis = null;
        private boolean bConnected = false;
        private DataOutputStream dos;

        public Client(Socket s) {
            this.s = s;

            try {
                dis = new DataInputStream(s.getInputStream());
                dos = new DataOutputStream(s.getOutputStream());
                bConnected = true;
                System.out.println("有一個新的客戶端程式在執行");
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 一個客戶端連線成功以後,一直在執行該while部分的程式碼,其他客戶端無法連線
            /**
             * 解決方法: 1.非同步解決方法:一直監聽接收,其他在另外的地方執行 2.使用單獨的執行緒: 執行緒:接受客戶端連線
             * 另外的單獨的執行緒:處理通訊
             */

        }

        public void sendString(String str) {
            try {
                dos.writeUTF(str);
            } catch (IOException e) {
                clients.remove(this);
                System.out.println("對方退出了!!!我從List中去掉了!!!");
            }
        }

        public void run() {
            Client client = null;
            // 注意這部分的包圍關係
            try {
                while (bConnected) {
                    String string = dis.readUTF();
                    System.out.println(string);
                    for (int i = 0; i < clients.size(); i++) {
                        client = clients.get(i);
                        client.sendString(string);
                    }
                }
            } catch (EOFException e) {
                System.out.println("Client closed!");
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(0);

            } finally {
                try {
                    if (dis != null) {
                        dis.close();
                    }
                    if (s != null) {
                        s.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

客戶端程式碼:


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.BindException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * 可以和ChatServer版本三配套使用
 * 
 * @author Administrator
 *
 */
public class ChatClientEdition3 extends Frame {
    TextField tfText = new TextField();
    TextArea taContent = new TextArea();
    Socket socket = null;
    DataOutputStream dataOutputStream = null;
    DataInputStream dataInputStream = null;
    private boolean bConnected = false;

    public static void main(String[] args) {

        new ChatClientEdition3().launchFrame();
    }

    // 載入視窗
    public void launchFrame() {
        setLocation(400, 300);
        this.setSize(300, 300);
        this.setTitle("線上聊天時--Quiana");
        add(tfText, BorderLayout.SOUTH);
        add(taContent, BorderLayout.NORTH);
        pack();
        // 視窗關閉的時間監聽
        this.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                disconnect();
                System.exit(0);
            }

        });
        tfText.addActionListener(new TFListener());
        this.setVisible(true);
        connect();
        new Thread(new RecvThread()).start();
    }

    // 文書處理的時間監聽
    private class TFListener implements ActionListener {
        // 敲擊回車時,文字的變化事件
        @Override
        public void actionPerformed(ActionEvent arg0) {
            String s = tfText.getText().trim(); // 去掉兩端的空格
            tfText.setText("");
            try {

                dataOutputStream.writeUTF(s);
                dataOutputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    // 連線到伺服器
    public void connect() {
        try {
            // 連線到伺服器
            socket = new Socket("127.0.0.1", 8888);
            bConnected = true;
            dataOutputStream = new DataOutputStream(socket.getOutputStream());
            dataInputStream = new DataInputStream(socket.getInputStream());
            System.out.println("連線到伺服器!!!");
        } catch (BindException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 斷開連線
    public void disconnect() {
        try {
            dataOutputStream.close();
            System.out.println("dataOutputStream成功關閉");
            socket.close();
            System.out.println("客戶端socket成功關閉");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class RecvThread implements Runnable {

        public void run() {

            try {
                while (bConnected) {
                    String string = dataInputStream.readUTF();
                    if (taContent.getText().length() == 0) {
                        taContent.setText(string);
                    } else {
                        taContent.setText(taContent.getText() + "\n" + string);
                    }
                }
            } catch (SocketException e) {
                System.out.println("退出了,拜拜!");
            } catch (EOFException e) {
                System.out.println("退出了,拜拜!");
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

}

相關文章