Socket 編程的demo(多線程版本)

前言

網絡編程的過程,類似於使用 QQ 的一個點對羣的聊天。
一個服務端,多個客戶端,客戶端發送信息到服務端,當發送的是 exit 時,就關閉當前連接,關閉的方式是使得線程運行結束。

項目

其實就是2個類。
一個是服務端,如果您有興趣,可以將這個線程池的方式更改爲 ThreadPoolExecutor 這個類。

服務端代碼

package thread.v1;

import javax.net.ServerSocketFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 服務端
 */
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocketFactory serverSocketFactory = ServerSocketFactory.getDefault();
        // 構建服務端 Socket 並設置端口
        ServerSocket serverSocket = serverSocketFactory.createServerSocket(9999);

        // 創建一個線程池
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        while(true){
            // 客戶端連接
            Socket socket = serverSocket.accept();
            executorService.submit(() -> {
                try {
                    // 客戶端輸入
                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String line;
                    while ((line = reader.readLine()) != null){
                        // 讀一行數據打印
                        System.out.println("客戶端來信:" + line);
                        if("exit".equals(line)){
                            System.err.println("客戶端 " + socket.getInetAddress().getHostAddress() + "正在退出連接!");
                            break;
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

客戶端代碼

package thread.v1;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 9999);

        // socket 獲取字符流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //通過標準輸入流獲取字符流
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));

        String line;
        while((line = bufferedReader.readLine()) != null){
            bufferedWriter.write(line);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }
    }
}

優化過的服務端

package thread.v1;

import javax.net.ServerSocketFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;

/**
 * 服務端
 */
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocketFactory serverSocketFactory = ServerSocketFactory.getDefault();
        // 構建服務端 Socket 並設置端口
        ServerSocket serverSocket = serverSocketFactory.createServerSocket(9999);

        // 創建一個線程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(60,
                100,
                20,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(20),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        while(true){
            // 客戶端連接
            Socket socket = serverSocket.accept();
            threadPoolExecutor.submit(() -> {
                try {
                    // 客戶端輸入
                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String line;
                    while ((line = reader.readLine()) != null){
                        // 讀一行數據打印
                        System.out.println("客戶端來信:" + line);
                        if("exit".equals(line)){
                            System.err.println("客戶端 " + socket.getInetAddress().getHostAddress() + "正在退出連接!");
                            break;
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

結果和總結

在這裏插入圖片描述

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