5

有没有人有关于例外“再试一次”的更多有用信息?

我正在使用LocalServerSocketand的应用程序之间发送位图LocalSocket

输出:

socket = new LocalSocket();
socket.connect(new LocalSocketAddress(SOCKET_NAME));
fos = new DataOutputStream(socket.getOutputStream());
...

public void onEvent() {
    fos.writeInt(width);
    fos.writeInt(height);
    fos.writeInt(newBuffer.length);
    fos.write(newBuffer);
}

输入:

server = new LocalServerSocket(SOCKET_NAME);
socket = server.accept(); 
socket.setSoTimeout(60);

while(true) {

    int width = fis.readInt(); // IO Exception being thrown here
    int height = fis.readInt(); 
    int length = fis.readInt();
    byte[] bytes = new byte[length];
    fis.read(bytes);
}

[为清楚起见,删除了 try/catch 等]

04-18 09:19:11.664: W/System.err(1268): java.io.IOException: Try again
04-18 09:19:11.664: W/System.err(1268):     at android.net.LocalSocketImpl.readba_native(Native Method)
04-18 09:19:11.664: W/System.err(1268):     at android.net.LocalSocketImpl.access$400(LocalSocketImpl.java:29)
04-18 09:19:11.664: W/System.err(1268):     at android.net.LocalSocketImpl$SocketInputStream.read(LocalSocketImpl.java:92)
04-18 09:19:11.664: W/System.err(1268):     at libcore.io.Streams.readFully(Streams.java:81)
04-18 09:19:11.664: W/System.err(1268):     at java.io.DataInputStream.readInt(DataInputStream.java:124)
04-18 09:19:11.664: W/System.err(1268):     at com.test.util.BitmapSendingUtils$BitmapReceiver$1.run(BitmapSendingUtils.java:105)
4

5 回答 5

4

您看到的异常可能是等同于 EAGAIN 错误的 java。参见例如这个答案

您应该处理异常并再次尝试失败的 IO 操作。

于 2013-04-28T07:48:46.450 回答
3

我已经重新设计了这个,因为我找不到解决方案。但是在以不同的方式实现它时,我在原始代码中遇到了这些错误:

byte[] bytes = new byte[length];
fis.read(bytes);

应该:

byte[] content = new byte[length];
int read = is.read(content);
while(read < content.length) {
    read += is.read(content, read, content.length - read);
}

因为.read(byte[])不会一下子吞下整个东西。我假设它这样做时会不断地啜饮和阻塞。

还有这个:

socket.setSoTimeout(60);

arg 以毫秒而不是秒为单位,因此应该是:

socket.setSoTimeout(60 * 1000);

我仍然不知道上述名称错误的异常的原因,所以希望有人知道的话仍然会回答这个问题!

于 2013-04-24T09:26:53.990 回答
0

尝试作为流,使用mInputValid控制是否结束流:

private int fill(byte[] buffer, int offset,int length) throws IOException {
    int sum = 0, len;
    while ((sum<length) && mInputValid) {
        try{
            len = is.read(buffer, offset + sum, length - sum);
            if (len < 0) {
                throw new IOException("End of stream");
            } else{
                sum += len;
                Log.i(TAG, "is.read: " + len + " buffer:" + buffer[0]);
            }
        }
        catch (IOException e){
            e.printStackTrace();
            Log.i(TAG, "read input fail, try again");
            continue;
        }
    }
    return sum;
}
于 2015-04-27T03:10:57.797 回答
0

我认为“再试一次” IOException 实际上应该以与处理 SocketTimeoutException 相同的方式处理。这是一个实现得很糟糕的 API,但我们已经习惯了 Android 上这种蹩脚的设计:

private int read(byte[] buffer) throws IOException {

    while (true) {
        try {
            return fis.read(buffer);
        } catch (SocketTimeoutException e) {
            continue;
        } catch (IOException e) {
            String message = e.getMessage();
            if (message != null && message.equals("Try again")) {
                continue;
            }
            throw e;
        }
    }
}

private int readInt() throws IOException {
    while (true) {
        try {
            return fis.readInt();
        } catch (SocketTimeoutException e) {
            continue;
        } catch (IOException e) {
            String message = e.getMessage();
            if (message != null && message.equals("Try again")) {
                continue;
            }
            throw e;
        }
    }
}
于 2015-11-03T15:19:50.430 回答
0

我知道我迟到了,但我刚刚解决了同样的问题,有很多事情会导致这个:

  1. 不要求outputStream.flush()发送。如果你使用作家,它是writer.flush(). 这将发送最后一个缓冲区。如果您不使用缓冲区,这并不意味着它们不存在。流以字节为单位发送数据,因此除非您发送单个字节,否则可能会有一些缓冲区未发送,并且接收器会获得半个 int。
  2. 如果您保持流打开,则无法检测到流的结束:因此,如果您尝试执行类似reader.read(buffer), 当大小buffer超过发送的数据量时,Java 将引发异常。在这种情况下,您必须实现某种 prototocle(标头告诉长度或某种结束标记,以知道何时停止阅读)。
  3. 如果您在发送消息和调用后关闭流output.flush(),则此异常可能是由您的意思引起的:套接字超时以及断开连接。
于 2016-10-22T19:41:14.753 回答