You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Socket客户端与服务端如何实现不受收发顺序限制的字符串读写

问题根因

当前代码采用单线程串行执行逻辑,两类阻塞操作(读取本地控制台输入的BufferedReader.readLine()、读取Socket对端消息的DataInputStream.readUTF())在同一线程中耦合执行:

  • 客户端循环逻辑为:读控制台输入→发消息→阻塞等待对端返回→打印返回,只要没输入新内容,就永远没法处理对端推送的消息
  • 服务端循环逻辑为:阻塞等待对端消息→打印→读控制台输入→发返回,只要没收到对端消息,就永远没法主动发消息给客户端
    这就导致了必须发一条才能收一条的时序异常。

解决方案

将「收消息」和「发消息」拆分为两个独立线程,各自执行阻塞逻辑互不干扰:

  • 主线程负责读取本地控制台输入,发送消息到对端
  • 单独启动一个子线程,死循环监听Socket输入流,收到消息直接打印,检测到end指令时关闭资源终止程序。

修改后的客户端代码

import java.io.*;
import java.net.Socket;

public class Client {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 1201);
            DataInputStream dInputStream = new DataInputStream(socket.getInputStream());
            DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
            BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));

            // 子线程:专门收服务端消息
            new Thread(() -> {
                try {
                    String msgin;
                    while ((msgin = dInputStream.readUTF()) != null) {
                        System.out.println("\n收到服务端消息:" + msgin);
                        if ("end".equals(msgin)) {
                            System.out.println("服务端已断开连接");
                            socket.close();
                            System.exit(0);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            // 主线程:专门发消息
            String msgout;
            while ((msgout = bReader.readLine()) != null) {
                dataOutputStream.writeUTF(msgout);
                dataOutputStream.flush();
                if ("end".equals(msgout)) {
                    Thread.sleep(100); // 等待end消息发送完成再关闭
                    socket.close();
                    System.exit(0);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

修改后的服务端代码

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(1201);
            Socket s = ss.accept();
            DataInputStream dInputStream = new DataInputStream(s.getInputStream());
            DataOutputStream dataOutputStream = new DataOutputStream(s.getOutputStream());
            BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));

            // 子线程:专门收客户端消息
            new Thread(() -> {
                try {
                    String msgin;
                    while ((msgin = dInputStream.readUTF()) != null) {
                        System.out.println("\n收到客户端消息:" + msgin);
                        if ("end".equals(msgin)) {
                            System.out.println("客户端已断开连接");
                            s.close();
                            System.exit(0);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            // 主线程:专门发消息
            String msgout;
            while ((msgout = bReader.readLine()) != null) {
                dataOutputStream.writeUTF(msgout);
                dataOutputStream.flush();
                if ("end".equals(msgout)) {
                    Thread.sleep(100);
                    s.close();
                    System.exit(0);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

逻辑说明

  1. 两端都可以随时输入内容发送,不需要等待对端返回,收到对端消息会立刻打印到控制台,不会被本地输入操作阻塞
  2. 任意一端输入end都会触发两端连接关闭、程序退出
  3. 新增的100ms休眠是为了保证end指令能正常发送到对端再关闭连接,避免消息丢失。

内容的提问来源于stack exchange,提问作者user16743592

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 00:12:02