杰瑞科技汇

java socket多线程客户端

Java Socket 多线程客户端实现

下面是一个完整的Java多线程Socket客户端实现示例,该客户端可以同时处理多个连接请求。

java socket多线程客户端-图1
(图片来源网络,侵删)

基本实现

import java.io.*;
import java.net.*;
import java.util.concurrent.*;
public class MultiThreadedSocketClient {
    private static final String SERVER_HOST = "localhost";
    private static final int SERVER_PORT = 12345;
    private static final int THREAD_POOL_SIZE = 5;
    public static void main(String[] args) {
        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
        // 启动多个客户端任务
        for (int i = 0; i < THREAD_POOL_SIZE; i++) {
            final int clientId = i + 1;
            executor.submit(() -> {
                try {
                    startClient(clientId);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
        // 关闭线程池
        executor.shutdown();
    }
    private static void startClient(int clientId) throws IOException {
        try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
            // 发送客户端ID
            out.println("Client-" + clientId + " connected");
            // 创建读取服务器响应的线程
            Thread responseThread = new Thread(() -> {
                try {
                    String response;
                    while ((response = in.readLine()) != null) {
                        System.out.println("Client-" + clientId + " received: " + response);
                    }
                } catch (IOException e) {
                    System.out.println("Client-" + clientId + " connection closed");
                }
            });
            responseThread.start();
            // 模拟客户端发送消息
            BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
            String userInput;
            while (true) {
                userInput = consoleReader.readLine();
                if ("exit".equalsIgnoreCase(userInput)) {
                    break;
                }
                out.println("Client-" + clientId + ": " + userInput);
            }
            responseThread.interrupt();
        }
    }
}

更高级的实现(带消息处理)

import java.io.*;
import java.net.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class AdvancedMultiThreadedClient {
    private static final String SERVER_HOST = "localhost";
    private static final int SERVER_PORT = 12345;
    private static final int MAX_THREADS = 10;
    private static final AtomicInteger clientIdCounter = new AtomicInteger(0);
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
        // 启动多个客户端
        for (int i = 0; i < MAX_THREADS; i++) {
            executor.submit(() -> {
                int clientId = clientIdCounter.incrementAndGet();
                try {
                    runClient(clientId);
                } catch (Exception e) {
                    System.err.println("Client " + clientId + " error: " + e.getMessage());
                }
            });
        }
        executor.shutdown();
    }
    private static void runClient(int clientId) throws IOException {
        try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
             DataOutputStream out = new DataOutputStream(socket.getOutputStream());
             DataInputStream in = new DataInputStream(socket.getInputStream())) {
            // 发送客户端ID
            out.writeInt(clientId);
            // 启动接收线程
            Thread receiverThread = new Thread(() -> {
                try {
                    while (!Thread.currentThread().isInterrupted()) {
                        String message = in.readUTF();
                        System.out.printf("Client %d received: %s%n", clientId, message);
                    }
                } catch (EOFException e) {
                    System.out.println("Client " + clientId + " server closed connection");
                } catch (IOException e) {
                    if (!Thread.currentThread().isInterrupted()) {
                        System.err.println("Client " + clientId + " receive error: " + e.getMessage());
                    }
                }
            });
            receiverThread.start();
            // 模拟发送消息
            Random random = new Random();
            for (int i = 0; i < 5; i++) {
                String message = "Message " + i + " from client " + clientId;
                out.writeUTF(message);
                System.out.println("Client " + clientId + " sent: " + message);
                try {
                    Thread.sleep(random.nextInt(2000)); // 随机延迟
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            // 关闭接收线程
            receiverThread.interrupt();
            receiverThread.join();
        }
    }
}

关键点说明

  1. 线程池管理:使用ExecutorService管理多个客户端连接,避免无限创建线程。

  2. 并发读写

    • 主线程负责发送消息
    • 专用线程负责接收服务器响应
    • 使用interrupt()机制优雅地关闭线程
  3. 连接管理

    • 使用try-with-resources确保资源自动关闭
    • 处理各种异常情况(如连接中断、服务器关闭等)
  4. 客户端标识

    java socket多线程客户端-图2
    (图片来源网络,侵删)
    • 每个客户端有唯一ID
    • 消息中包含客户端标识便于追踪
  5. 消息格式

    • 使用DataOutputStreamDataInputStream处理二进制数据
    • 也可以使用PrintWriterBufferedReader处理文本数据

测试建议

  1. 先实现一个简单的Socket服务器来测试客户端
  2. 可以增加心跳机制保持连接活跃
  3. 考虑添加重连逻辑处理临时连接中断
  4. 对于生产环境,建议使用NIO或Netty等更高效的框架

这个实现提供了基本的Socket多线程客户端功能,可以根据具体需求进行扩展和优化。

java socket多线程客户端-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇