2014-09-19 60 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();