Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么输入流以块的形式读取数据?_Java_Sockets_Network Programming_Inputstream - Fatal编程技术网

Java 为什么输入流以块的形式读取数据?

Java 为什么输入流以块的形式读取数据?,java,sockets,network-programming,inputstream,Java,Sockets,Network Programming,Inputstream,我正在尝试使用以下代码从网络套接字读取一些数据- Socket s = new Socket(address, 502); response = new byte[1024]; InputStream is = s.getInputStream(); int count = is.read(response, 0, 100); 数据量不大。总共是16个字节。但是read()语句并不是一次性读取所有数据。它只将8字节的数据读入我的缓冲区 我必须像这样多次调用read(),才能读取数据- Sock

我正在尝试使用以下代码从网络套接字读取一些数据-

Socket s = new Socket(address, 502);
response = new byte[1024];
InputStream is = s.getInputStream();
int count = is.read(response, 0, 100);
数据量不大。总共是16个字节。但是read()语句并不是一次性读取所有数据。它只将8字节的数据读入我的缓冲区

我必须像这样多次调用read(),才能读取数据-

Socket s = new Socket(address, 502);
response = new byte[1024];
InputStream is = s.getInputStream();
int count = is.read(response, 0, 100);
count += is.read(response, count, 100-count);
为什么会这样?为什么read()不能一次读取整个流

请注意,数据不是逐渐到达的。如果我在调用Thread.sleep(2000)读取数据之前等待2秒钟,行为将保持不变

为什么read()不能一次读取整个流

因为没有指定要这样做。请参阅Javadoc。它阻塞直到至少有一个字节可用,然后返回介于1和提供的长度(包括1)之间的数字

这反过来又是因为数据不一定是一次性到达的。您无法控制TCP发送和接收数据的方式。您必须将其视为字节流


我知道它会一直阻塞,直到数据到达。“这反过来是因为数据不一定一次就全部到达。”我的问题是为什么不

数据不一定全部一次性到达,因为网络通常会将其分解为数据包。IP是一种分组交换协议

TCP是否传输8字节的数据块

可能,但可能不是。数据包大小取决于数据所经过的网络,但典型的internet数据包大小约为1500字节

如果您一次获得8个字节,则可能是您的数据通过数据包大小异常小的网络传输,或者(更有可能)发送方一次发送8个字节的数据。第二种解释或多或少与你的其他评论相矛盾

既然我显式地指定了100,这个数字比缓冲区中的数据大得多,它不应该尝试读取至少100个字节吗

嗯,不。它不是指定以那种方式工作的,它也不是以那种方式工作的。您需要根据规范中的说明编写代码



这可能与设备被“轮询”的方式有关。但是,如果不查看设备的规格(甚至不知道它到底是什么),这只是一个猜测。

可能数据是逐渐到达的,不是因为您的阅读,而是因为发件人


发送方应该在发送之前使用a(中间)来制作大块(并且仅在需要时使用flush)。

通常,您会在第二次调用中使用第一次调用的结果(在
计数中)作为偏移量(现在硬编码为
8
)(并且在检查EOS时在while循环中执行调用)。@martijno I会这样做。但这不是我的困惑。为什么会这样?插座的另一边是什么?你能控制的东西?@martijno这是一个热传感器。每次我轮询它时,它都会响应16字节的状态数据。我通过在OutputStream中写入几个字节来轮询它。我知道它会阻塞直到数据到达。“这反过来是因为数据不一定一次就全部到达。”我的问题是为什么不。TCP是否以8字节的块进行传输?由于我明确指定了100,这个数字比缓冲区中的数据大得多,它不应该尝试读取至少100个字节吗?@kshitizzarma如果接收缓冲区中有100个字节,它可能会给你100个字节,如果有8个字节,它会给你8个字节。如果1字节可用,它将为您提供1。如果没有可用的字节,它将被阻塞。@PeterLawrey我理解流和缓冲区是如何工作的。流仅返回缓冲区中的可用内容。我明白了。我的问题是关于缓冲区的行为。为什么100Mbps TCP以太网上只有8个字节?@kshitizzarma为什么只有8个字节?通过查看数据如何写入流,您可能能够回答这些问题。如果你想控制(至少是控制)从InputStream读取的内容和方式,你需要将其包装在BufferedReader或类似的东西中…@GermannArlington,这不会有丝毫区别,更不用说给你任何“控制”。在发送方使用
BufferedOutputStream
BufferedWriter
可能会有所不同。我不想争论,但这并不能解决我的困惑。该网络为100mbps以太网。因此,数据包大小应该相当大。如果设备以8字节的卡盘缓慢传输,那么使用Thread.sleep(2000)等待2秒应该会填满缓冲区,你不这么认为吗?@kshitizzarma-我认为这与此无关。重要的是你在实践中看到了什么。@kshitizzarma在理论上,理论和实践是一样的。实际上,它们不是