Android &引用;IOException:再试一次;使用LocalServerSocket时

Android &引用;IOException:再试一次;使用LocalServerSocket时,android,localserversocket,localsocket,Android,Localserversocket,Localsocket,有人有关于“重试”异常的更多有用信息吗 我正在使用LocalServerSocket和LocalSocket在应用程序之间发送位图: 输出: socket = new LocalSocket(); socket.connect(new LocalSocketAddress(SOCKET_NAME)); fos = new DataOutputStream(socket.getOutputStream()); ... public void onEvent() { fos.writeIn

有人有关于“重试”异常的更多有用信息吗

我正在使用
LocalServerSocket
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)

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

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);
}
arg的单位是毫秒而不是秒,因此应为:

socket.setSoTimeout(60 * 1000);

我仍然不知道上述名称不正确的异常的原因,尽管如此,如果有人知道,希望他们仍然会回答这个问题

您看到的异常可能是与EAGAIN错误相当的java。例如,见


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

尝试作为流,使用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;
}
private int fill(字节[]缓冲区、int偏移量、int长度)引发IOException{
整数和=0,len;
虽然((sum我认为“重试”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;
        }
    }
}

我知道我参加聚会迟到了,但我刚刚解决了同一个问题,有很多事情可能导致这种情况:

  • 发送时不调用
    outputStream.flush()
    。如果使用writer,则为
    writer.flush()
    。这将发送最后一个缓冲区。如果不使用缓冲区,并不意味着它们不存在。流式传输以字节为单位发送数据,因此,除非您发送单个字节,否则很可能有一些缓冲区未被发送,而接收者得到半个整数
  • 如果您保持流开放,则无法检测流的结束:因此,如果您尝试执行
    reader.read(buffer)
    ,当
    缓冲区的大小超过发送的数据量时,Java将抛出异常。在这种情况下,您必须实现某种协议(标题告诉长度或某种结束标记,以知道何时停止读取)
  • 如果您在发送消息并调用
    output.flush()
    后关闭流,则此异常可能由您的意思引起:套接字超时以及断开连接

  • 它引发了一个特定的阻塞操作。看起来上面的答案不适用。嗯,无论如何,它不应该适用。啊,我明白了。这是LocalSocketImpl中的一个错误吗?如果您将错误视为EAGAIN并重试,会发生什么?
    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;
            }
        }
    }