2012-03-13 40 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