簡體   English   中英

在AsyncTask中維護TCP連接

[英]Maintaining a TCP Connection in an AsyncTask

我正在使用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的連接, doInBackground也沒做,直到我調用SendDataToNetwork並將字節發送到服務器后,才等到准備好發送新數據為止? 基本上,我想運行AsyncTask,直到我明確取消(=關閉連接)為止。

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

測試毫無意義。 如果未連接套接字,則connect()會引發異常。

您的讀取循環從根本上還是有缺陷的,因為它不會一直讀取。 有關如何讀取流的標准解決方案,例如:

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

您的waitForSocketToConnect()方法實際上也沒有做任何有用的事情。

您需要重新考慮所有這一切。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM