Socket OutputStream.write() 阻塞行为

Socket OutputStream.write() Blocking Behaviour

这是我的客户端程序:

public class Client {
  public static void main(String[] args) {
    try {
      Socket socket = new Socket("127.0.0.1", 6123);
      DataOutputStream dos =
          new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));

      File file = new File("/Users/prashantpandey/Desktop/737_cdu_preflight.mp4");
      Long fileLength = file.length();
      System.out.println("File's Length is: " + fileLength + " bytes");

      InputStream is = new FileInputStream(file);

      byte[] bytes = new byte[8192];

      OutputStream os = socket.getOutputStream();

      int count = 0;
      int counter = 0;
      while ((count = is.read(bytes)) > 0) {
        System.out.println(counter++);
        System.out.println("Writing bytes: " + count);
        System.out.println("About to write the above bytes");
        os.write(bytes, 0, count);
        System.out.println("Finished writing the above bytes");
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

对于服务器运行的每个循环,我让它休眠 15 秒。我观察到的是客户端非常快速地将 8192 bytes 数据写入套接字的 OutputStream 大约 100 个计数,然后阻塞很长时间。另一方面,服务器从套接字的 InputStream.

的每个循环中继续读取数据

这是我的服务器:

public class Server {
  public static void main(String[] args) {
    try {

      System.out.println("Entry thread: " + Thread.currentThread().getName());
      ServerSocket ss = new ServerSocket(6123);

      System.out.println("Waiting for accept: " + Thread.currentThread().getName());
      Socket socket = ss.accept();


      DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

      int count = 0;
      byte[] buffer = new byte[8192];

      while ((count = dis.read(buffer)) > 0) {
        System.out.println("Printing Received Data: \n" + new String(buffer));
        Thread.sleep(15000);
      }


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

正如我提到的,服务器在每个循环中不断读取数据。它始终在套接字上可用以供读取。

有人可以向我解释为什么客户端线程在大约 100 次计数后等待这么长时间吗? OS 级别发生了什么?

假定您在服务器每次读取后休眠 15 秒,并且客户端以全速发送数据,很可能套接字缓冲区和缓冲输出流在下一次读取之前就已经完全满了服务器发生。因此,客户端将被阻塞,等待 space 在缓冲输出流中可用(并间接在套接字缓冲区中可用),假设这只会以每 15 秒 8192 字节(最大)的增量发生,最终客户端每 15 秒最多只能发送 8192 字节。

从您的服务器中删除睡眠,问题应该会消失。