2014-09-19 65 views
2

我想通过tcp从一个android设备发送消息到另一个。发送设备发送到用作服务器的PC,然后将该消息发送到其他设备。 为了接收消息,我运行一个与UI线程平行的线程,它使用处理程序更新用户界面以显示消息。这工作正常。Android:与工作线程通信发送消息

现在我正在使用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 recevied文本。有没有类似于接收线程的解决方案?我很努力地告诉创建的线程什么时候发送消息,而不从该线程访问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); 
} 
} 
+0

你需要使用处理程序,但以相反的方式...尝试HandlerThread – Selvin 2014-09-19 10:27:45

回答

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();