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

时间:2014-09-19 10:19:39

标签: java android multithreading sockets tcp

我正在尝试通过tcp将消息从一个Android设备发送到另一个设备。发送设备发送到用作服务器的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);
}
}

1 个答案:

答案 0 :(得分:1)

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

您的读者线程需要改进 - 当没有可用输入时,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
 }  

在您的UI中使用

发送消息
writerThread.sendMessage( "Whatever you want to send );

完成线程后用

完成
writerThread.stopWriter();