【问题标题】:Does java socket read the data exactly as it's sentjava socket 是否完全按照发送的方式读取数据
【发布时间】:2015-04-28 14:53:54
【问题描述】:

假设我们在两个设备(A 和 B)之间有一个套接字连接。现在,如果我只将 16 个字节(大小在这里无关紧要)写入 A 侧套接字的输出流(不是 BufferedOutputStream)3 次或通常不止一次,如下所示:

OutputStream outputStream = socket.getOutputStream();
byte[] buffer = new byte[16];
OutputStream.write(buffer);
OutputStream.write(buffer);
OutputStream.write(buffer);

我使用套接字输入流(不是 BufferedInputStream)读取 B 侧的数据,其缓冲区大于发送缓冲区,例如 1024:

InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
int read = inputStream.read(buffer);

现在我想知道 B 方如何接收数据?它可能会累积还是在 A 发送数据时准确读取数据?换句话说,read 变量可能会超过 16?

【问题讨论】:

  • 这一切都取决于时间。如果 B 在尝试读取时已接收到所有输入,则它将读取所有 16*3 字节。但如果到那时只发送了其中的一两个,它只会读取那些。
  • 如果在发送前开始读取呢? @乔恩
  • @Ali:此方法阻塞,直到输入数据可用、检测到文件结尾或抛出异常。
  • @Ali 我建议阅读 Oracle Tutorial on I/O Streams 以更好地了解它们在内部的实际工作方式。

标签: java sockets


【解决方案1】:

InputStream 很少保证任何多字节read() 方法的调用将读取多少数据。有一整类常见的编程错误围绕着对此的误解和错误假设。例如,

  • 如果InputStream.read(byte[]) 读取的字节数少于所提供的数组可以容纳的字节数,这表示已到达流的末尾,甚至另一次读取必然会阻塞。
  • InputStream.read(byte[]) 的任何一次调用读取的字节数不一定与流绘制的字节源的任何特征相关,除非它在不在末尾时总是读取至少一个字节流,并且它不会在返回时读取比实际可用更多的字节。
  • available() 方法指示的可用字节数不能可靠地指示后续读取应该或将读取多少字节。非零返回值仅可靠地表明下一次读取不会阻塞;零返回值告诉您什么都没有

子类可以保证其中一些行为,但大多数都没有,而且您通常不知道您实际拥有哪个子类。

为了正确使用InputStreams,您通常必须准备执行重复读取,直到获得足够的数据来处理。这可能意味着读取直到您累积了特定数量的字节,或者读取直到遇到分隔符。在某些情况下,您可以处理来自任何给定读取的任意数量的字节;通常在这些情况下,您无论如何都在循环,并将您读取的所有内容提供给可以接受可变长度块的消费者(例如,许多压缩和加密接口都是这样的)。

【讨论】:

    【解决方案2】:

    根据文档:

    public int read(byte[] b) throws IOException
    

    从输入流中读取一些字节并将它们存储到缓冲区数组 b 中。字节数 实际读取以整数形式返回。此方法阻塞,直到 输入数据可用,检测到文件结尾,或出现异常 抛出。如果 b 的长度为零,则不读取任何字节并且 0 回来;否则,将尝试读取至少一个字节。如果 没有字节可用,因为流位于文件末尾, 返回值 -1;否则,至少读取并存储一个字节 进入b。

    读取的第一个字节存储到元素 b[0] 中,下一个字节存储到 b[1],以此类推。读取的字节数最多等于 b的长度。设 k 为实际读取的字节数;这些字节 将存储在元素 b[0] 到 b[k-1] 中,留下元素 b[k] 通过 b[b.length-1] 不受影响

    Read(...) 告诉您它放入数组的字节数,是的,您可以进一步阅读;你会得到任何已经存在的东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 1970-01-01
      • 2017-01-19
      • 1970-01-01
      • 2019-09-07
      相关资源
      最近更新 更多