Android - 多线程TCP连接

时间:2013-12-25 15:30:39

标签: java android multithreading tcp android-asynctask

我一直在寻找我的问题的答案,但到目前为止没有一个解决方案帮助我解决它。我正在开发一个与另一个用作服务器的设备通信的应用程序。该应用程序向服务器发送查询并接收适当的响应以动态创建片段。

在第一个实现中,app发送了查询,然后等待在单个线程中接收答案。但该解决方案并不令人满意,因为该应用程序未收到服务器的任何反馈。服务器管理员说他正在接收查询,但他暗示该设备发送回答的速度太快,并且应用程序在答案到达时可能还没有收听。

所以我想要实现的是创建单独的线程:一个用于监听,一个用于发送查询。在我们向服务器发送任何内容之前,侦听的内容将启动,以确保应用程序不会错过服务器响应。

到目前为止,实现这一点并不成功。我已经尝试编写并运行单独的Runnable类和AsyncTasks,但是侦听器从未收到过答案,并且在某些时候其中一个线程甚至没有执行。以下是asynctask侦听器的代码:

            @Override
        protected String doInBackground(String... params) {

            int bufferLength = 28;
            String masterIP = "192.168.1.100";

            try {
                Log.i("TCPQuery", "Listening for ReActor answers ...");
                Socket tcpSocket = new Socket();
                SocketAddress socketAddress = new InetSocketAddress(masterIP, 50001);
                try {               
                    tcpSocket.connect(socketAddress);
                    Log.i("TCPQuery", "Is socket connected: " + tcpSocket.isConnected());

                } catch (IOException e) {
                    e.printStackTrace();
                }

                while(true){

                    Log.i("TCPQuery", "Listening ...");
                    try{
                        Log.i("TCPQuery", "Waiting for ReActor response ...");
                        byte[] buffer = new byte[bufferLength];
                        tcpSocket.getInputStream().read(buffer);
                        Log.i("TCPQuery", "Received message " + Arrays.toString(buffer) + " from ReActor.");
                    }catch(Exception e){
                        e.printStackTrace();
                        Log.e("TCPQuery", "An error occured receiving the message.");
                    }
                }

            } catch (Exception e) {
                Log.e("TCP", "Error", e);
            }

            return "";
        }

这就是调用任务的方式:

        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
          listener.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
          sender.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
        }
        else {
          listener.execute();
          sender.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }

你究竟会如何解决这个问题?如果这段代码不够用,我很乐意发布更多内容。

2 个答案:

答案 0 :(得分:1)

这是因为Android的AsyncTask实际上只是一个线程,无论你创建多少个,所以如果你真的想要同时运行两个线程,我建议你使用标准的Java并发包工具,而不是{ {1}}。正如in the documentation所述:

  

AsyncTask旨在成为Thread和Handler的辅助类   并不构成通用的线程框架。 AsyncTasks   理想情况下应该用于短期操作(几秒钟的时间)   大多数。)如果你需要保持线程长时间运行,   强烈建议您使用提供的各种API   java.util.concurrent pacakge ,例如Executor,ThreadPoolExecutor和   FutureTask。

答案 1 :(得分:0)

看这是tcp连接。所以你不需要为数据丢失而烦恼。这是端口到端口的连接,它永远不会发送流的结束(-1)。也许你必须关心阅读功能。因为你不能顺应所有接受的蒸汽。 Tcp读取方法是阻塞调用。如果您的读缓冲区大小小于可用的流大小,则它将阻塞,直到它可以完全读取。并且您使用的是Android设备,可能的流可能会因您的设备网络而异。所以你有2个选择, 1)您的缓冲区大小应该是动态的。首先使用is.available()检查可用的输入流大小,然后按此大小创建buf大小。如果可用大小为零,则休眠一段时间以检查它是否丢失了其流可用性。 2)设置输入流超时。它确实有效,因为它读取其可用流并等待超时延迟,如果任何流在超时期限内不可用,则它会抛出超时异常。 尝试更改您的代码。