【问题标题】:Android - multithread TCP connectionAndroid - 多线程 TCP 连接
【发布时间】:2014-01-13 11:42:13
【问题描述】:

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

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

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

到目前为止,实施这一点还没有成功。我尝试编写和运行单独的 Runnable 类和 AsyncTasks,但侦听器从未收到答案,并且在某些时候其中一个线程甚至没有执行。这是异步任务监听器的代码:

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

您将如何解决这个问题?如果此代码还不够,我很乐意发布更多内容。

【问题讨论】:

  • 我忘了说运行单个线程,无论是侦听器还是发送者都可以正常工作。

标签: java android multithreading tcp android-asynctask


【解决方案1】:

这是因为Android的AsyncTask其实只是一个线程,不管你创建多少,所以如果你真的想要2个线程同时运行,我建议你使用标准的Java并发打包工具,而不是AsyncTask .正如in the documentation解释的那样:

AsyncTask 被设计成一个围绕 Thread 和 Handler 的辅助类 并且不构成通用线程框架。异步任务 理想情况下应用于短操作(几秒钟在 大多数。)如果您需要保持线程长时间运行, 强烈建议您使用由 java.util.concurrent 包,例如Executor、ThreadPoolExecutor和 未来任务。

【讨论】:

  • 我也尝试过使用基本的 Java 线程,但没有成功。您将如何使用标准 Java 线程来解决问题?我刚刚创建了两个线程,每个线程都有连接服务器的代码,然后我一个接一个地调用它们,但结果如前所述。
  • 我有一个服务(在 Android 4.1 中),有几个线程正在运行,它们运行良好。在上面的代码中,您没有显示您如何发送接收,只显示接收。我不知道您的程序的逻辑,但我建议一个用于发送的套接字和另一个用于接收的套接字(这意味着您的设备中也有一个服务器端)。
  • 我尝试了一种类似的方法,但我只使用了一个 Socket。基本上,连接是在“主”线程中建立的,在套接字启动并运行后,我分别运行两个单独的线程(使用该套接字)监听器和发送器。该方法似乎有效,但是我还没有机会使用实际设备对其进行测试(它适用于我自己的服务器实现)。如果您对我的解决方案有任何疑问,我将不胜感激额外的反馈,但当我有机会用真正的交易测试它时,我会无限期地发布更多信息。到目前为止,谢谢!
  • 实际证明,解决方案与我想象的有所不同。问题实际上并不在于构造的线程部分,而是在于设备尝试重新连接回应用程序,但应用程序没有等待连接的服务器套接字。对“服务器”设备机制的误解。再次感谢大家。
【解决方案2】:

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

【讨论】:

  • “可用流可能会因您的设备网络而异” 我认为这不正确,数据如何因网络而异?对我来说毫无意义。网络与设备类型无关,手机和PC一样。
  • 看,假设您的总流强度为 500。可用流永远不会发送相等的长度。它可能会在某个时间返回 50、100、30 0 等等。因此,如果您收到 0,那么您必须等待一段时间并设置读取超时以检查进一步的可用性。如果没有可用的流,那么它将自动抛出 readtimeout 异常。我之前遇到过这个问题,我通过这种机制处理了这个问题。试试这个,你的问题一定会解决的。
  • 首先我不是问这个问题的人,其次我从来没有遇到过这个问题。如果您发送 500 字节,您将收到 500 字节,无论源/目标设备是什么,除非当然网络出现故障,在这种情况下您当然会收到异常。
猜你喜欢
  • 1970-01-01
  • 2013-01-07
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-13
  • 1970-01-01
相关资源
最近更新 更多