java - Android FileChannel 在不同的 AsyncTask 中读写失败

标签 java android multithreading sockets android-asynctask

我有一个 Service 类,它通过本地套接字与另一个进程(比如 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。我还尝试在服务中创建一对输入/输出 FileChannel 并将这两个 FileChannel 传递给 AsyncTask,但仍然面临同样的问题。

非常感谢任何帮助!

最佳答案

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

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

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

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

关于java - Android FileChannel 在不同的 AsyncTask 中读写失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42319251/

相关文章:

java - J2ME文本字段加倍

java - 对字符串进行快速排序

java - 无法使用 JERSEY 下载文件

java - 按钮文本垂直对齐在 Android 中关闭

java - 如何在 ArrayList 中使用 set() 而不出现错误?

Android:如何在 ActionBarSherlock 选项卡中加载 Activity ?

java - 如何处理线程中的异常?

java - AVL 树 - 找到所需的 : String,:AVL

java - newFixedThreadPool 的内部工作

c - 使用多线程计算数据但并没有减少时间