简体   繁体   English

写入比从套接字读取更快

[英]Writing faster than reading from a socket

I did an experiment and I created a program with 2 threads: a server thread and a client thread.我做了一个实验,我创建了一个有 2 个线程的程序:一个服务器线程和一个客户端线程。 The server thread accepts a connection from the client, does a long process (emulated by sleep() ), and prints the result.服务器线程接受来自客户端的连接,执行一个长过程(由sleep()模拟),并打印结果。

The client on the other hand sends messages really fast.另一方面,客户端发送消息的速度非常快。

See the code:看代码:

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();
        }
    }
}

When I ran the program I got the following output:当我运行程序时,我得到以下输出:

Hello!
Hello!
llo!
o!

ello!
lo!
!
Hello!
llo!
o!

ello!
lo!
!
Hello!
llo!
o!

ello!
lo!
!
Hello!
llo!
o!

ello!
...

Now I am not sure I understand it 100%... But I did run the experiment of using an input the size of a power of 2 (including /n ) and the output was not cut off.现在我不确定我是否 100% 理解它......但我确实运行了使用大小为 2 的幂(包括/n )的输入的实验,并且输出没有被切断。

Can someone explain to me:谁能给我解释一下:

  1. What's going on internally?内部发生了什么?
  2. Why no error is thrown?为什么不抛出错误?
  3. What would you do to overcome this problem?你会怎么做来克服这个问题?

Thanks!!谢谢!!

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();

This creates a new BufferedReader for each run of while loop.这会为每次运行 while 循环创建一个新的BufferedReader But readline will not only read a line from the socket.但是readline不仅会从套接字读取一行。 It will instead read a larger amount of data, check if there is a line end in it, read more if no line end yet etc and finally return the line.相反,它将读取大量数据,检查其中是否有行尾,如果还没有行尾则读取更多数据等,最后返回该行。 The rest of the read data is kept in the BufferedReader .其余的读取数据保存在BufferedReader By implicitly abandoning the BufferedReader at the end of loop run and creating a new one at the beginning of a new loop run you abandon all data in the buffer which were already read from the socket.通过在循环运行结束时隐式放弃BufferedReader并在新循环运行开始时创建一个新的,你放弃了缓冲区中已经从套接字读取的所有数据。

Instead you should create your BufferedReader outside the loop and use it there so that no data gets abandoned:相反,您应该在循环外创建您的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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM