简体   繁体   English

使用LocalServerSocket时“IOException:再试一次”

[英]“IOException: Try again” while using LocalServerSocket

Does anybody have more helpful information on the Exception "Try again"? 有没有人有关于例外“再试一次”的更多有用信息?

I'm sending Bitmaps between apps using LocalServerSocket and LocalSocket : 我正在使用LocalServerSocketLocalSocket在应用程序之间发送位图:

Output: 输出:

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);
}

Input: 输入:

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 etc removed for clarity] [为了清晰起见,删除了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)

The exception you see is probably the java equivalent to the EAGAIN error. 您看到的异常可能是与EAGAIN错误等效的java。 See for example this answer . 例如,请参阅此答案

You should handle the exception and try the failed IO operation again. 您应该处理异常并再次尝试失败的IO操作。

I've since rengineered this as I couldn't find the solution. 我已经重新设计了这个,因为我找不到解决方案。 But while implementing it a different way I came across these errors in the original code: 但是在以不同的方式实现它时,我在原始代码中遇到了这些错误:

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

Should be: 应该:

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

as .read(byte[]) doesn't slurp the whole thing at once. 因为.read(byte[])不会.read(byte[])整个事物。 I assumed that this continually slurped and blocked while it did so. 我认为这种情况持续不断地淤塞和封锁。

There is also this: 还有这个:

socket.setSoTimeout(60);

The arg is in millis rather than seconds so should be: arg是毫秒而不是秒,所以应该是:

socket.setSoTimeout(60 * 1000);

I still don't know the cause of the above badly named exception though so hopefully someone will still answer this if they know! 我仍然不知道上述严重命名的异常的原因,但希望如果他们知道,有人仍会回答这个问题!

try as flow, use mInputValid to control whether end the flow: 尝试作为流,使用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;
}

I think the "Try again" IOException should actually be handled in the same way a SocketTimeoutException would be handled. 我认为“再试一次”IOException实际上应该以与处理SocketTimeoutException相同的方式处理。 This is a very poorly implemented API, but we are used to such crappy design on Android: 这是一个执行得很差的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;
        }
    }
}

I know I am late to the party, but I just solved the same issue and there are a number of things that can cause this: 我知道我迟到了,但我刚解决了同样的问题,有很多事情可以导致这个问题:

  1. Not calling outputStream.flush() on sending. 在发送时不调用outputStream.flush() If you use writers, it's writer.flush() . 如果你使用编剧,那就是writer.flush() This sends the last buffer. 这将发送最后一个缓冲区。 If you are not using buffers, it doesn't mean they aren't there. 如果您不使用缓冲区,并不意味着它们不在那里。 Stream send data in bytes, so unless you are sending a single byte, chances are there's some buffer down the line that doesn't get sent, and the receiver gets half an int. 流以字节为单位发送数据,因此,除非您发送单个字节,否则可能会有一些缓冲区在线路上没有被发送,并且接收器获得半个int。
  2. If you are keeping the streams open, there is no way to detect the stream's end: so the Java will thrown an exception if you try to do things like reader.read(buffer) , when size of the buffer exceeds the amount of data sent. 如果要保持流的开放,则无法检测流的结束:因此,如果尝试执行reader.read(buffer) ,当buffer大小超过发送的数据量时,Java将抛出异常。 In this case you must implement some kind of prototocle (header telling the length or some sort of end token, to know when to stop reading). 在这种情况下,你必须实现某种prototocle(标题告诉长度或某种结束标记,知道何时停止阅读)。
  3. If you are closing streams after sending message and calling output.flush() , this exception can be caused by what you meantioned: socket timeouts, as well as disconnects. 如果在发送消息并调用output.flush()之后关闭流,则此异常可能由您的意思引起:套接字超时以及断开连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM