【问题标题】:Android FileChannel read & write fails in different AsyncTaskAndroid FileChannel 读写在不同的 AsyncTask 中失败
【发布时间】:2017-02-18 18:46:38
【问题描述】:

我有一个服务类,它通过本地套接字与我的另一个进程(比如说 process_A)进行通信。

我的服务类如下:

public class MyService extends Service {
    private LocalSocket localSock;
    private LocalSocketAddress localSockAddr;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent.getAction().equals(START_SERVICE_ACTION)) {
            localSock = new LocalSocket();
            localSockAddr = new LocalSocketAddress(LOCAL_SOCK_ADDR, LocalSocketAddress.Namespace.ABSTRACT);
            try {
                localSock.connect(localSockAddr);
            } catch (IOException e) {
                // Ignore
            }

            if (localSock.isConnected()) {
                new LocalSockInitTask().execute(localSock);
            }
        } else if (intent.getAction().equals(STOP_SERVICE_ACTION)) {
            new LocalSockTermTask().execute(localSock);
        }
    }
}

行为应该如下:

  1. 当用户启动我的服务时,该服务使用 LocalSocket.connect() 与 process_A 连接。连接成功后,服务会执行 AsyncTask 以向 process_A 发送 INIT 消息并等待来自 process_A 的 INIT 消息。
  2. 当我的服务被用户停止时,该服务会执行另一个 AsyncTask 以向 process_A 发送 TERM 消息并等待来自 process_A 的 TERM 消息。

LocalSockInitTask.java:

public class LocalSockInitTask extends AsyncTask<LocalSocket, Void, Boolean> {
    @Override
    protected Boolean doInBackground(LocalSocket... params) {
        LocalSocket localSock = params[0];
        FileChannel inChannel;
        FileChannel outChannel;
        ByteBuffer sendBuf, recvBuf;
        byte[] bytes;
        String result, recvMsg;
        int attempt;

        try {
            inChannel = new FileInputStream(localSock.getFileDescriptor()).getChannel();
            outChannel = new FileOutputStream(localSock.getFileDescriptor()).getChannel();

            // Send INIT Message
            sendBuf = ByteBuffer.wrap(MSG_INIT.getBytes());
            outChannel.write(sendBuf);

            // Wait for INIT Message
            recvBuf = ByteBuffer.allocate(BUFFER_SIZE);
            attempt = 0;
            while (inChannel.read(recvBuf) < 0) {
                attempt++;
                if(attempt == 5)
                    return false;

                Thread.sleep(1000);
            }

            recvBuf.flip();
            bytes = new byte[recvBuf.remaining()];
            recvBuf.get(bytes);

            result = new String(bytes);
            if(!result.equals(MSG_INIT))
                return false;

            inChannel.close();
            outChannel.close();

            return true;
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }
}

LocalSockTermTask.java 与 LocalSockInitTask.java 几乎相同,主要区别只是发送和接收的消息是“MSG_TERM”。

Init 任务执行得很完美,写入和读取都成功。但是,在执行第二个 AsyncTask(即 LocalSockTermTask)时,似乎写入和读取都不成功。我在这条线上做了一些测试:

inChannel.read(recvBuf);

在第一次 AsyncTask 执行 (LocalSockInitTask) 中,如果没有任何内容可以读取,此方法将立即返回 -1,这就是我设置 while 循环并计算尝试次数的原因。

在第二次AsyncTask执行(LocalSockTermTask)中,如果什么都读不出来,这个方法就会被阻塞,这使得我的while循环和尝试计数变得毫无用处。这会导致 AsyncTask 永远不会完成。另外,我的 process_A 正在等待“MSG_TERM”终止,并且它仍然在运行,这就是为什么我认为 outChannel.write(sendBuf) 在 Term 任务中也失败了。

目前我将 LocalSocket 对象传递给 AsyncTask 并在 AsyncTask 中创建一对输入/输出 FileChannel。我也尝试在服务中创建一对 in/out FileChannel 并将这两个 FileChannel 传递给 AsyncTask,但仍然面临同样的问题。

非常感谢任何帮助!

【问题讨论】:

    标签: java android multithreading sockets android-asynctask


    【解决方案1】:

    好的,我刚刚发现这是我粗心的错误。问题解决了。

    1. 我的另一个进程错误地处理了 TERM 消息,所以它只是简单地忽略了我的 AsyncTask 发送的 TERM 消息,因此它继续运行并等待消息。

    2. 由于它忽略了 TERM 消息,它不会向我的 AsyncTask 发送回 TERM 消息,这导致 inChannel.read(recvBuf) 没有可读取的内容。

    3. inChannel.read(recvBuf)的阻塞行为是绝对正常的,返回-1应该是我在改用BufferedReader之前使用BufferedReader的情况。

    【讨论】:

      猜你喜欢
      • 2017-12-04
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2019-04-18
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多