2012-03-13 37 views
0

我正在使用AsyncTask建立TCP連接並通過它發送/接收數據。在AsyncTask中維護TCP連接

我當前的代碼看起來像這樣的時刻:

public class NetworkTask extends AsyncTask<Void, byte[], Boolean> { 
    Socket nsocket; //Network Socket 
    InputStream nis; //Network Input Stream 
    OutputStream nos; //Network Output Stream 
    boolean bSocketStarted = false; 
    byte[] buffer = new byte[4096]; 

    @Override 
    protected void onPreExecute() { 
     Log.i(TAG, "onPreExecute"); 
    } 

    @Override 
    protected Boolean doInBackground(Void... params) { //This runs on a different thread 
     boolean result = false; 
     try { 
      // Connect to address 
      Log.i(TAG, "doInBackground: Creating socket"); 
      SocketAddress sockaddr = new InetSocketAddress("google.de", 80); 
      nsocket = new Socket(); 
      nsocket.connect(sockaddr, 5000); //10 second connection timeout 
      if (nsocket.isConnected()) { 
       bSocketStarted = true; 
       nis = nsocket.getInputStream(); 
       nos = nsocket.getOutputStream(); 
       Log.i("AsyncTask", "doInBackground: Socket created, streams assigned"); 
       Log.i("AsyncTask", "doInBackground: Waiting for inital data..."); 
       int read = nis.read(buffer, 0, 4096); //This is blocking 
       while(bSocketStarted) { 
        if (read > 0){ 
         byte[] tempdata = new byte[read]; 
         System.arraycopy(buffer, 0, tempdata, 0, read); 
         publishProgress(tempdata); 
         Log.i(TAG, "doInBackground: Got some data"); 
        } 
       } 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
      Log.i(TAG, "doInBackground: IOException"); 
      result = true; 
     } catch (Exception e) { 
      e.printStackTrace(); 
      Log.i(TAG, "doInBackground: Exception"); 
      result = true; 
     } finally { 
      try { 
       nis.close(); 
       nos.close(); 
       nsocket.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      Log.i(TAG, "doInBackground: Finished"); 
     } 
     return result; 
    } 

    public boolean SendDataToNetwork(final byte[] cmd) { //You run this from the main thread. 
     // Wait until socket is open and ready to use 
     waitForSocketToConnect(); 

     if (nsocket.isConnected()) { 
      Log.i(TAG, "SendDataToNetwork: Writing received message to socket"); 
      new Thread(new Runnable() { 
       public void run() { 
        try { 
         nos.write(cmd); 
        } 
        catch (Exception e) { 
         e.printStackTrace(); 
         Log.i(TAG, "SendDataToNetwork: Message send failed. Caught an exception"); 
        } 
       } 
      } 
        ).start(); 
      return true; 
     } 
     else 
      Log.i(TAG, "SendDataToNetwork: Cannot send message. Socket is closed"); 

     return false; 
    } 

    public boolean waitForSocketToConnect() { 
     // immediately return if socket is already open 
     if (bSocketStarted) 
      return true; 

     // Wait until socket is open and ready to use 
     int count = 0; 
     while (!bSocketStarted && count < 10000) { 
      try { 
       Thread.sleep(500); 
      } 
      catch (InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 
      count += 500; 
     } 

     return bSocketStarted; 
    } 

    @Override 
    protected void onProgressUpdate(byte[]... values) { 
     try { 
      if (values.length > 0) { 
       Log.i(TAG, "onProgressUpdate: " + values[0].length + " bytes received."); 

       String str = new String(buffer, "UTF8"); 
       Log.i(TAG,str); 
       tv.setText(str); 
       tv.setMovementMethod(new ScrollingMovementMethod()); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     finally {} 
    } 
    @Override 
    protected void onCancelled() { 
     Log.i(TAG, "Cancelled."); 
    } 
    @Override 
    protected void onPostExecute(Boolean result) { 
     if (result) { 
      Log.i(TAG, "onPostExecute: Completed with an Error."); 

     } else { 
      Log.i(TAG, "onPostExecute: Completed."); 
     } 
    } 
} 

我可以實例化的任務,並從我的活動叫SendDataToNetwork。但是,我將所有傳遞給SendDataToNetwork的文本(例如「GET/HTTP/1.1」)連續發送到服務器。

如何修改我的代碼保持doInBackground連接,什麼也不做,直到我打電話SendDataToNetwork和發送字節到服務器後,只是等待,直到新的數據已經準備好要發送?基本上我想運行AsyncTask直到我明確地取消(=關閉連接)它。

+0

爲什麼要打開連接?用戶可能會經過一條隧道(或者如果你住在英國:在任何一個方向上走1步),然後再丟失信號。 – 2012-03-13 10:27:22

+0

這適用於某種類似telnet的應用程序,因此您可以發出原始SMTP或HTTP命令。只要屏幕處於活動狀態,或者直到用戶按下用於此目的的斷開按鈕,我纔想保持連接。 – Flo 2012-03-13 14:46:39

回答

3
nsocket.connect(sockaddr, 5000); //10 second connection timeout 
if (nsocket.isConnected()) { 

該測試沒有意義。如果套接字未連接,則connect()將引發異常。

您的閱讀循環也存在根本性缺陷,因爲它不會繼續閱讀。有標準的解決方案,爲如何讀取流,例如:

while ((count = in.read(buffer)) > 0) 
{ 
    out.write(buffer, 0, count); 
} 

waitForSocketToConnect()方法並沒有真正做任何有用的事情無論是。

您需要重新考慮這一切。

+0

感謝您的回答。根據您的代碼更改while循環並刪除不必要的功能可以修復所有問題。 – Flo 2012-03-13 13:27:58