写入比从套接字读取更快

Writing faster than reading from a socket

我做了一个实验,我创建了一个有 2 个线程的程序:一个服务器线程和一个客户端线程。 服务器线程接受来自客户端的连接,执行一个长过程(由 sleep() 模拟),并打印结果。

另一方面,客户端发送消息的速度非常快。

见代码:

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketTest {

    public static void main(String[] args) throws InterruptedException {
        Thread serverThread = new Thread(() -> server());
        Thread clientThread = new Thread(() -> client());

        serverThread.start();
        clientThread.start();

        serverThread.join();
        clientThread.join();
    }

    private static void server() {
        try (
            ServerSocket listener = new ServerSocket( 1234 );
            Socket client = listener.accept()){  // wait for connection

            while (true) {
                InputStream in = client.getInputStream();

                // read a newline or carriage-return-delimited string
                BufferedReader bin =
                        new BufferedReader( new InputStreamReader( in ) );
                String someString = bin.readLine();
                //process
                Thread.sleep(1000);
                System.out.println(someString);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void client () {
        try (Socket server = new Socket(InetAddress.getLocalHost(), 1234))
        {
            while (true) {
                OutputStream out = server.getOutputStream();

                // write a newline or carriage return delimited string
                PrintWriter pout = new PrintWriter(out, true);
                pout.println("Hello!");

                // send the the string
                pout.flush();
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

当我 运行 程序时,我得到以下输出:

Hello!
Hello!
llo!
o!

ello!
lo!
!
Hello!
llo!
o!

ello!
lo!
!
Hello!
llo!
o!

ello!
lo!
!
Hello!
llo!
o!

ello!
...

现在我不确定我是否理解了 100%... 但是我做了运行输入大小为2的幂(包括/n)的实验,输出没有被截断。

谁能给我解释一下:

  1. 内部情况如何?
  2. 为什么没有报错?
  3. 你会怎样克服这个问题?

谢谢!!

private static void server() {
    ...
        while (true) {
            InputStream in = client.getInputStream();

            // read a newline or carriage-return-delimited string
            BufferedReader bin =
                    new BufferedReader( new InputStreamReader( in ) );
            String someString = bin.readLine();

这会为 while 循环的每个 运行 创建一个新的 BufferedReader。但是 readline 不仅会从套接字中读取一行。相反,它将读取大量数据,检查其中是否有行尾,如果还没有行尾则读取更多数据等等,最后 return 该行。其余的读取数据保存在BufferedReader中。通过在循环 运行 结束时隐式放弃 BufferedReader 并在新循环 运行 开始时创建一个新循环 运行 ,您放弃了缓冲区中已经从套接字读取的所有数据.

相反,您应该在循环外创建 BufferedReader 并在那里使用它,这样就不会放弃任何数据:

private static void server() {
    ...
        InputStream in = client.getInputStream();
        BufferedReader bin =
                new BufferedReader( new InputStreamReader( in ) );

        while (true) {
            // read a newline or carriage-return-delimited string
            String someString = bin.readLine();