输入流无法处理 2016 字节

huangapple go评论80阅读模式
英文:

InputStream can't handle 2016 bytes

问题

以下是翻译好的内容:

最近我用Java编写了一个程序,可以自动创建加密连接并传输与其有关的数据。现在我遇到的问题是,如果一次传输大量数据,输入流不再响应。(我尝试一次性传输了2016字节的数据)

但我认为问题可能与低字节和高字节的传输有关。

服务器端:

    public byte[] read() throws IOException {
        byte[] bytes = new byte[2];
        this.inputStream.read(bytes);
        int length = ((bytes[0] & 0xff) << 8) | (bytes[1] & 0xff);
        byte[] buffer = new byte[length];
        this.inputStream.read(buffer);
        return this.encryption.decryptAES(buffer);
    }

客户端:

    public void write(byte[] message) throws IOException {
        byte[] bytes = new byte[2];
        message = this.encryption.encryptAES(message);
        bytes[1] = (byte) (message.length & 0xFF);
        bytes[0] = (byte) ((message.length >> 8) & 0xFF);
        this.outputStream.write(bytes);
        this.outputStream.write(message);
    }

输入流未关闭或为空。
也没有抛出任何异常。

程序在服务器端读取字节以获取字节数组的长度时挂起。在客户端,字节成功地被发送。

英文:

I recently wrote a program in Java that automatically creates encrypted connections and transmits data about them. Now I have the problem that the input stream no longer reacts if a lot of data is transferred at once. (I tried to transfer 2016 bytes at once)

But i think the problem is about the low an high byte transmission.

Server:

    public byte[] read() throws IOException {
        byte[] bytes = new byte[2];
        this.inputStream.read(bytes);
        int length = ((bytes[0] &amp; 0xff) &lt;&lt; 8) | (bytes[1] &amp; 0xff);
        byte[] buffer = new byte[length];
        this.inputStream.read(buffer);
        return this.encryption.decryptAES(buffer);
    }

Client:

    public void write(byte[] message) throws IOException {
        byte[] bytes = new byte[2];
        message = this.encryption.encryptAES(message);
        bytes[1] = (byte) (message.length &amp; 0xFF);
        bytes[0] = (byte) ((message.length &gt;&gt; 8) &amp; 0xFF);
        this.outputStream.write(bytes);
        this.outputStream.write(message);
    }

InputStreams aren't closed or null.
No exception was thrown either.

The programm hangs up at reading the bytes for the length of the byte array on serverside. On Client side the bytes are successfully send.

答案1

得分: 3

read调用正在按设计工作; 你只是对其设计方式感到困惑(必须承认,这有点奇怪)。

read(byteArray)方法保证会读取至少1字节;只有在发生异常或流关闭时才不会读取任何字节。

但是,它并不保证填满提供的字节数组。它只读取1字节也是完全可以的(规范说这样是可以的,因此,你的代码必须编写来处理这种情况)。即使还有更多要发送的数据。

那么,你实际上会得到多少字节呢?¯\(ツ)/¯ 取决于你的网络适配器、操作系统、虚拟机和月相。

因此,像这样的“孤立”读取调用总是有问题的。它必须出现在某种循环中。

幸运的是,除非你使用的是相当旧的Java版本,否则你不必编写任何代码来处理这些问题;现在的InputStream类型有 readNBytes 方法,它将保证填充整个提供的字节数组,只有在发生异常或流在填充完整字节数组之前结束时,才会给你较少的字节。

因此,不要使用:in.read(buffer),正确的调用方式是 in.readNBytes(buffer, 0, buffer.length)

注意:read的设计是这样的,因为它与I/O的实际工作方式相吻合:我现在可以给你2016字节;如果你需要更多,这会花更长时间(另一次与适配器的往返,或者可能要等待IP数据包穿越海洋,谁知道那需要多长时间);而且通常情况下,你不太可能知道使你的字节数组具有最快响应速度的神奇大小,同时又不会产生太多的read()请求,这样做也会很慢 —— 因此,你不能通过这样说来解决这个困境:“好吧,如果你想要快速响应,就给一个小字节数组!” 现在你知道为什么设计成这样了 输入流无法处理 2016 字节

英文:

The read call is working as designed; you're just confused about how it is designed (which is admittedly a little bizarre).

The read(byteArray) method is guaranteed to read at least 1 byte; it will only read none if an exception occurs, or the stream is closed.

It is not, however, guaranteed to fill the provided byte array. It's perfectly fine for it to read only 1 byte (the spec says this is okay, thus, your code must be written to deal with it). Even if there's more to be sent.

So, how many bytes do you actually end up getting? ¯_(ツ)_/¯ Depends on your network card, the OS, the VM, and the phase of the moon.

Therefore, a 'lone' read call like this is always a bug. It must occur in some sort of loop.

Fortunately, you don't have to program any of that unless you're on a rather old version of java; these days the InputStream type has the readNBytes method, which will guarantee that it will fill the entire provided byte array, giving you fewer bytes only if an exception occurs or if the stream ends before the full byte array is filled.

So, instead of: in.read(buffer), the right call is in.readNBytes(buffer, 0, buffer.length).

NB: The design of read is like this because it meshes with how I/O actually works: I can give you 2016 bytes right now; if you want more, it would take longer (another round trip to the card, or possibly waiting for IP packets to make their way across an ocean, who knows how long that might take); and often it is not really possible for you to know that the magic size to make your byte array so that you get the fastest possible response without making unwieldily many requests to read() which would also be slow – thus, you can't solve this dilemma by saying: "Well, just give a small byte array if you want fast responses!". Now you know why it is designed like this 输入流无法处理 2016 字节

huangapple
  • 本文由 发表于 2020年3月17日 04:25:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/60712764.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定