【问题标题】:How to get data to/from a socket in a thread?如何从线程中的套接字获取数据?
【发布时间】:2011-05-20 09:44:55
【问题描述】:

这里是安卓菜鸟。通过查看功能示例的源代码,我学到了最好的东西,但是我一直无法找到在自己的线程中使用套接字的简单但完整的示例。

我有一个需要与 Internet 通信的 Android 服务。我想打开一个连接到 Internet 上服务器的 TCP 套接字。服务需要将数据发送到 Internet,而从网络返回的数据也需要发送到服务。由于服务也在做其他事情,因此套接字连接需要存在于自己的线程中。

知道在哪里可以找到与套接字通信的线程中的套接字示例吗?

谢谢

【问题讨论】:

    标签: android multithreading sockets


    【解决方案1】:

    您只需创建一个在后台通信的异步任务,然后根据需要更新 UI 线程。这是从套接字获取信息并使用它接收的字节数更新文本视图的后台线程

      public class InternetTask extends AsyncTask<Void, Integer, Void> {
    
        private WeakReference<TextView> mUpdateView;
    
        public LoginTask(TextView view) {
            this.mUpdateView = new WeakReference<TextView>(view);
        }
    
        @Override
        protected Void doInBackground() {
    
            try {
                Socket socket = new Socket("127.0.0.1", 80);
                        InputStream is = socket.getInputStream();
    
                        byte[] buffer = new byte[25];
                        int read = is.read(buffer);
                        while(read != -1){
                             publishProgress(read);
                             read = is.read(buffer);
                        }
    
                        is.close();
                        socket.close();
    
    
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        @Override
        protected void onProgressUpdate(Integer... values) {
            if(mUpdateView.get() != null && values.length > 0){
                         mUpdateView.get().setText(values[0].toString());
                    }
        }
    
    }
    

    这就是你将如何启动该线程

    public class TestTab extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.someLayout);
    
                TextView textView = (TextView)findViewById(R.id.someid);
                InternetTask task = new InternetTask(textView);
                task.execute();
    
        }
    }
    

    【讨论】:

    • 有没有办法在 AsyncTask 启动后向它发送额外的数据,以便数据可以从套接字发送出去?我看到了如何使用 publishProgress 和 onProgressUpdate 将数据从后台线程获取到 UI 线程,但我没有看到在任务运行时如何走其他路。
    • 您可以在异步任务上定义您想要的任何其他方法。只需知道 doInBackground() 方法将是唯一在单独线程上执行的方法。您也可以在构造函数中或将要发送的数据传递给 execute() 方法。
    • 当我在 doInBackground() 中打开一个套接字时,该新线程将被阻塞,直到数据进入套接字。当数据进来时,我可以通过 publishProgress 将它发送到 UI 线程。由于套接字是在该工作线程上创建的,我如何从 UI 线程向套接字发送数据?我在处理一个数据流,所以用execute()命令发送参数很好,但是我需要不断地向socket发送数据。
    • 您将任务视为任何其他对象,并以正常方式为其提供数据。它只是在一个单独的线程中运行。
    • 我认为InternetTask 构造函数中有错字。它应该是 public InternetTast(TextView view) 而不是 public LoginTask(TextView view)
    【解决方案2】:

    这是一个关于这个主题的长博客,其中显示了服务器和客户端部分,套接字通信通过单独的线程进行。

    http://thinkandroid.wordpress.com/2010/03/27/incorporating-socket-programming-into-your-applications/

    需要注意的一点是,如果您传递ints,您可能会遇到字节顺序问题,因此,只需进行一些测试,我建议您确保服务器以Android 需要,以防您在多个操作系统上拥有服务器。

    对于一个简单的方法,在Android上查找字节顺序可以使用这个:http://developer.android.com/reference/java/nio/ByteOrder.html

    根据这篇文章,可以交换字节顺序进行优化: http://en.wikipedia.org/wiki/Dalvik_(software)

    【讨论】:

    • 这是我见过的最清晰的代码,展示了如何创建套接字。然而,虽然服务器示例展示了如何将数据发送回 UI 线程(通过处理程序),但两个示例都没有展示如何将数据从 UI 线程移动到套接字线程。
    • 您可以使用 View.post 返回 UI 线程,但此页面可能会以其他方式帮助您:developer.android.com/guide/appendix/faq/…
    猜你喜欢
    • 2012-09-10
    • 1970-01-01
    • 2014-04-09
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    • 2021-05-17
    相关资源
    最近更新 更多