下面是一个简单的示例,演示如何使用消息边界标记解决 TCP 粘包问题。在这个示例中,消息边界标记是换行符 \n

服务端代码:

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

public class TCPServer {
    public static void main(String[] args) {
        final int PORT = 8888;

        try {
            ServerSocket serverSocket = new ServerSocket(PORT);
            System.out.println("Server started...");

            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Client connected: " + clientSocket);

                // 创建一个新线程处理客户端连接
                Thread clientThread = new Thread(new ClientHandler(clientSocket));
                clientThread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class ClientHandler implements Runnable {
    private Socket clientSocket;

    public ClientHandler(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);

            String line;
            StringBuilder message = new StringBuilder();
            while ((line = in.readLine()) != null) {
                if (line.isEmpty()) {
                    // 遇到空行表示消息结束,处理完整消息
                    handleMessage(message.toString(), out);
                    message.setLength(0); // 清空消息缓冲区
                } else {
                    message.append(line).append("\n"); // 将数据添加到消息缓冲区
                }
            }

            in.close();
            out.close();
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void handleMessage(String message, PrintWriter out) {
        // 在这里处理完整消息,示例中只是简单地将收到的消息原样返回给客户端
        System.out.println("Received from client: " + message);
        out.println("Echo: " + message);
    }
}

客户端代码:

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

public class TCPClient {
    public static void main(String[] args) {
        final String SERVER_IP = "127.0.0.1"; // 服务器 IP 地址
        final int SERVER_PORT = 8888; // 服务器端口号

        try {
            Socket socket = new Socket(SERVER_IP, SERVER_PORT);
            System.out.println("Connected to server...");

            BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            String line;
            while ((line = userInput.readLine()) != null) {
                out.println(line); // 将用户输入发送给服务器
                String response = in.readLine(); // 读取服务器的回复
                System.out.println("Server response: " + response);
            }

            userInput.close();
            out.close();
            in.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这个示例中,服务端在处理客户端发送的数据时,会等待读取到空行,表示一个完整的消息结束。然后将完整的消息传递给 handleMessage() 方法进行处理。这样可以确保每个消息都是完整的,避免了粘包问题。