java socket是否完全按照它发送的方式读取数据

时间:2015-04-28 14:53:55

标签: java sockets

考虑我们在两个设备(A和B)之间有一个套接字连接。现在,如果我只将16个字节(这里的大小并不重要)写入A侧套接字的输出流(不是BufferedOutputStream),或者通常不止一次这样写:

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?

2 个答案:

答案 0 :(得分:2)

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

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

子类可以对这些行为中的某些行为提供保证,但大多数行为都没有,并且无论如何您通常不知道您实际拥有哪个子类。

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

答案 1 :(得分:1)

根据文档:

public int read(byte[] b) throws IOException
  

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

     

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

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