有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在异步任务中维护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,直到显式取消(关闭连接)它


共 (1) 个答案

  1. # 1 楼答案

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

    这个测试毫无意义。如果套接字未连接,connect()将引发异常

    你的阅读循环也存在根本缺陷,因为它无法持续阅读。有关于如何读取流的标准解决方案,例如:

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

    你的waitForSocketToConnect()方法也没有真正起到任何作用

    你需要重新考虑这一切