java - Android:与工作线程通信发送消息

标签 java android multithreading sockets tcp

我正在尝试通过 tcp 从一台 Android 设备向另一台设备发送消息。发送设备发送到用作服务器的 PC,然后 PC 将消息发送到其他设备。 为了接收消息,我运行一个与 UI 线程并行的线程,该线程使用处理程序更新用户界面以显示消息。这工作得很好。

现在我正在使用 AsyncTask 发送消息,它创建一个套接字,然后发送消息,然后再次关闭套接字。因此,每次我想发送消息时,我都必须连接和断开连接。

public class SendTask extends AsyncTask<String, Void, Void> {

static final String TAG = "SendTask";

private Socket soc;
private String theIp;
private int thePort;

public SendTask(String pIp, int pPort){
    theIp = pIp;
    thePort = pPort;
}

@Override
protected Void doInBackground(String... arg0) {

    try {
        soc = new Socket(theIp, thePort);
        soc.getOutputStream().write(arg0[0].getBytes());
        soc.close();
    } catch (Exception e) {
        Log.d(TAG, "failed to create socket");      
        e.printStackTrace();
    }

    return null;
}

}

我宁愿有一个解决方案,我创建一个线程来打开套接字,然后每次单击按钮时都会发送从 EditText 接收的文本。有没有类似于接收线程的解决方案?我正在努力解决如何告诉创建的线程何时发送消息而不从该线程访问 UI。

发送线程如下所示:

public class ReceiveClient implements Runnable {

static final String TAG = "ReceiveClient";

public static final int NEW_INPUT = 101;

private Socket soc;
private String theIp;
private int thePort;
Handler handler;

public ReceiveClient(String pIp, int pPort, Handler pHandler){
    this.theIp = pIp;
    this.thePort = pPort;
    handler = pHandler;
}

@Override
public void run() {
    Log.d(TAG, "try to create socket");
    try {
        soc = new Socket(theIp, thePort);
    } catch (Exception e) {
        Log.d(TAG, "failed to create socket");      
        e.printStackTrace();
    }
    Log.d(TAG, "running");
    try {
        while (!Thread.currentThread().isInterrupted()) {
            byte b[] = new byte[16];
            int count = soc.getInputStream().read(b, 0, 16);
            if(count > 0){
                String s = new String(b);
                Log.d(TAG, "received: " + s);
                displayMessage(s);
                }
            }
        Log.d(TAG, "done");
        }catch (Exception e) {
            System.err.println(e);
    }
}

private void displayMessage(String text){
    Message msg = handler.obtainMessage();
    msg.what = NEW_INPUT;
    msg.obj = text;
    handler.sendMessage(msg);
}
}

最佳答案

我建议你使用某种阻塞队列。在单独的线程中处理读取和写入 - 这是线程安全的,即如果一个线程从套接字读取而另一个线程向它写入,则不会发生任何冲突。

您的阅读器线程需要改进 - 当没有可用输入时,InputStream.read 将阻塞,因此您的 Thread.isInterrupted 检查是无用的。相反,我建议您跳过 isInterrupted 检查并在想要停止读取时关闭套接字,这将导致您的 read() 解除阻塞。

在你的作者线程中做这样的事情

 private ArrayBlockingQueue<String> writerQueue = new ArrayBlockingQueue<String>( 10 );
 private String stopSignal = "whatever";       

 public void stopWriter() { // this can safely called from other threads and will cause writer thread to stop
     writerQueue.put( stopSignal );     
 } 

 // this can also safely called from other threads
 public void sendMessage( String newMessage ) {
     writerQueue.put( newMessage );
 }

 @Override
 public void run() {
     String currentMessage = writerQueue.take(); // if there are no messages in queue this will block
     if( currentMessage == stopSignal ) // == comparison here is correct! we want to check for object equality 
         return; // stop signal received
     // write your string here
 }  

在您的用户界面中使用以下方式发送消息

writerThread.sendMessage( "Whatever you want to send );

完成后,完成线程

writerThread.stopWriter();

关于java - Android:与工作线程通信发送消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25931649/

相关文章:

java - 如何更改列表中 bean 的属性值?

java - 在非 Android Java 项目中使用 Android 应用程序的一部分

java - Android Button onClick运行方法,不幸的是App已经停止

java - 通过 JSONObject 传递 Unicode 字符串时出错

Android 操作栏 SearchView 作为自动完成?

android - 创建自定义 View 作为可跨项目使用的模块化和可重用组件

c++ - 将 boost::asio::post 用于接受参数的函数

php - android-php-mysql : json + rmi

c++ - 在 C Linux 中使用三个线程使用信号量同步按顺序打印 3 4 5 50 次

Java:尽管执行非常简单的任务,线程仍需要很长时间才能完成