1. 程式人生 > >java socket多執行緒實現聊天室

java socket多執行緒實現聊天室

java socket多執行緒實現聊天室

程式碼放在我的GitHub上點選檢視

版本1,一對一,收發有順序

/**
 * @Author: Hzw
 * @Time: 2018/4/19 11:38
 * @Description: 聊天室客戶端V1.0,雙向通訊,客戶端傳送後服務端才可以傳送,客戶端傳送前伺服器傳送的話,
 * 訊息儲存在緩衝區中,等待客戶端傳送訊息後,緩衝區的訊息才會傳送
 */
public class ChatClient {

    private Socket socket;

    public ChatClient(){
        try
{ this.socket = new Socket("127.0.0.1", 8888); } catch (IOException e) { e.printStackTrace(); } } public void start(){ try{ OutputStream outputStream = socket.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter
(outputStream); PrintWriter pw = new PrintWriter(osw, true); Scanner sc = new Scanner(System.in); InputStream inputStream = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(inputStream); BufferedReader br = new BufferedReader
(isr); while (true){ pw.println(sc.nextLine()); System.out.println(br.readLine()); } }catch (Exception e){ e.printStackTrace(); }finally { if (socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String[] args){ ChatClient client = new ChatClient(); client.start(); } } /** * @Author:
Hzw * @Time: 2018/4/19 11:59 * @Description: */ public class ChatServer { private ServerSocket serverSocket; public ChatServer(){ try { this.serverSocket = new ServerSocket(8888); } catch (IOException e) { e.printStackTrace(); } } public void start(){ try { //接收客戶端傳送的訊息 Socket socket = serverSocket.accept(); InputStream inputStream = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(inputStream, "utf-8"); BufferedReader br = new BufferedReader(isr); //傳送訊息給客戶端 OutputStream outputStream = socket.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(outputStream); PrintWriter pw = new PrintWriter(outputStream, true); Scanner scanner = new Scanner(System.in); while (true){ System.out.println(br.readLine()); pw.println(scanner.nextLine()); } }catch (Exception e){ e.printStackTrace(); } } public static void main(String[] args){ ChatServer chatServer = new ChatServer(); chatServer.start(); } }

版本2,一對一,多執行緒,收發無順序

/**
 * @Author: Hzw
 * @Time: 2018/4/19 14:01
 * @Description: 由於版本1客戶端和伺服器都有收發功能,並且收發有相應的順序,都對應相應的阻塞:緩衝區br.readLine(),
 *               鍵盤輸入sc.nextLine(),版本2將改進,將收發分配給相應的執行緒處理,避免了阻塞
 */
@SuppressWarnings("all")
public class ChatClient {

    private Socket socket;

    public ChatClient(){

        try {
            socket = new Socket("127.0.0.1", 8888);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start(){

        Thread sendThread = new Thread(new SendThread());
        Thread receiveThread = new Thread(new ReceiceThread());
        sendThread.start();
        receiveThread.start();
    }

    public static void main(String[] args){

        ChatClient chatClient = new ChatClient();
        chatClient.start();
    }


    public class SendThread implements Runnable{

        @Override
        public void run() {
            try {
                OutputStream outputStream = socket.getOutputStream();
                OutputStreamWriter osw = new OutputStreamWriter(outputStream);
                PrintWriter pw = new PrintWriter(osw, true);
                Scanner scanner = new Scanner(System.in);

                while (true){
                    pw.println(scanner.nextLine());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public class ReceiceThread implements Runnable{

        @Override
        public void run() {
            try {
                InputStream inputStream = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(inputStream);
                BufferedReader br = new BufferedReader(isr);

                while (true){
                    System.out.println(br.readLine());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * @Author: Hzw
 * @Time: 2018/4/19 14:00
 * @Description:
 */
@SuppressWarnings("all")
public class ChatServer {

    private ServerSocket serverSocket;
    private Socket socket;

    public ChatServer(){
        try {
            serverSocket = new ServerSocket(8888);
            socket = serverSocket.accept();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start(){

        Thread sendThread = new Thread(new SendThread());
        Thread receiveThread = new Thread(new ReceiveThread());
        sendThread.start();
        receiveThread.start();
    }

    public static void main(String[] args){

        ChatServer chatServer = new ChatServer();
        chatServer.start();
    }

    public class SendThread implements Runnable{

        @Override
        public void run() {
            try {
                OutputStream outputStream = socket.getOutputStream();
                OutputStreamWriter osw = new OutputStreamWriter(outputStream);
                PrintWriter pw = new PrintWriter(osw, true);
                Scanner scanner = new Scanner(System.in);

                while(true){
                    pw.println(scanner.nextLine());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public class ReceiveThread implements Runnable{

        @Override
        public void run() {
            try {
                InputStream inputStream = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(inputStream);
                BufferedReader br = new BufferedReader(isr);

                while (true){
                    System.out.println(br.readLine());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

版本3,一對多,收發無順序,多執行緒

/**
 * @Author: Hzw
 * @Time: 2018/4/19 14:48
 * @Description: 改進:版本2中由於serverSocket.accept()只執行一次,所以只能一對一通訊,一對多通訊必須有多個socket,並存儲在server屬性中作為集合儲存
 *                  ReceiveThread將獲取的socket存入集合中,send都遍歷這個集合,實現群發功能
 *                  但是由於阻塞,所以一個執行緒不能處理多個socket,所以必須一個執行緒處理一個socket,建立執行緒的時候必須傳入socket,main中每次接收一個,就建立對應的接收執行緒
 *                  群發訊息流程是建立對應的接收執行緒後,將socket加入集合,遍歷集合socket,給每個回話傳送訊息,而且輸入scanner只輸入一次,所以在main中輸入
 *                  由於這個輸入會阻塞,後面有連線到來的時候服務端accept執行不到,所以將輸入做成執行緒,防止阻塞.
 */
@SuppressWarnings("all")
public class ChatServer {

    private ServerSocket serverSocket;
    private List<Socket> socketList = new ArrayList<>();

    public ChatServer(){

        try {
            serverSocket = new ServerSocket(8889);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start(){

    }

    public static void main(String[] args){

        ChatServer chatServer = new ChatServer();
        while (true){
            try {
                Socket socket = chatServer.serverSocket.accept();
                chatServer.socketList.add(socket);
                System.out.println("新的連線" + socket.getPort());

                Thread receiveThread = new Thread(new ReceiveThread(socket));
                receiveThread.start();

                SendMessage sendMessage = new SendMessage(chatServer.socketList);
                Thread thread = new Thread(sendMessage);
                thread.start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static class SendMessage implements Runnable{

        private List<Socket> socketList;

        public SendMessage(List<Socket> socketList){
            this.socketList = socketList;
        }

        @Override
        public void run() {
            Scanner scanner = new Scanner(System.in);
            String s = scanner.nextLine();
            for (Socket socket1 : socketList) {
                Thread sendThread = new Thread(new SendThread(socket1, s));
                sendThread.start();
            }
        }
    }

    public static class SendThread implements Runnable{

        private Socket socket;
        private String s;

        public SendThread(Socket socket){
            this.socket = socket;
        }

        public SendThread(Socket socket, String s){
            this.socket = socket;
            this.s = s;
        }

        @Override
        public void run() {
            try {
                OutputStream outputStream = socket.getOutputStream();
                OutputStreamWriter osw = new OutputStreamWriter(outputStream);
                PrintWriter pw = new PrintWriter(osw, true);
                pw.println(s);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static class ReceiveThread implements Runnable{

        private Socket socket;

        public ReceiveThread(Socket socket){
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                InputStream inputStream = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(inputStream);
                BufferedReader br = new BufferedReader(isr);

                while (true){
                    System.out.println(br.readLine());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * @Author: Hzw
 * @Time: 2018/4/19 14:49
 * @Description:
 */
@SuppressWarnings("all")
public class ChatClient {
    private Socket socket;

    public ChatClient(){

        try {
            socket = new Socket("127.0.0.1", 8889);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start(){

        Thread sendThread = new Thread(new SendThread());
        Thread receiveThread = new Thread(new ReceiceThread());
        sendThread.start();
        receiveThread.start();
    }

    public static void main(String[] args){

        ChatClient chatClient = new ChatClient();
        chatClient.start();
    }


    public class SendThread implements Runnable{

        @Override
        public void run() {
            try {
                OutputStream outputStream = socket.getOutputStream();
                OutputStreamWriter osw = new OutputStreamWriter(outputStream);
                PrintWriter pw = new PrintWriter(osw, true);
                Scanner scanner = new Scanner(System.in);

                while (true){
                    pw.println(scanner.nextLine());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public class ReceiceThread implements Runnable{

        @Override
        public void run() {
            try {
                InputStream inputStream = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(inputStream);
                BufferedReader br = new BufferedReader(isr);

                while (true){
                    System.out.println(br.readLine());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}