1

我们在 Android 中遇到了一些非常奇怪的行为。我们的网络堆栈(与 REST 服务器通信)几乎在所有情况下都能正常工作,除非我们在执行较大的 POST 后不久执行 GET。似乎正在发生的事情是输出流没有刷新,并最终发送打开新套接字时那里的最后一行。请注意,每个连接都是一个新创建的对象,因此这是意外行为。首先,似乎将我指向输出流的错误代码,这些来自服务器日志。

10.1.8.195 - - [07/Nov/2012:13:36:28 -0700]“POST /iou/lender HTTP/1.1”200 28“-”“Android”10.1.8.195 - - [2012 年 11 月 7 日: 13:36:36 -0700]“------------V2ymHFg03ehbqgZCaKO6jy”400 173“-”“-”

之后的尝试应该是 GET,然后从服务器中提取数据,其中包括通过 POST 添加的新条目。然而,我们得到的只是 POST 输出流的最后一行。这是我们网络栈的核心代码,如果需要更多的周边代码,请告诉我。

public Object serverConnect(String url, String method,
        Hashtable<String, Object> params) {

    HttpConnection c = null;
    InputStream is = null;
    OutputStream out = null;
    ByteArrayOutputStream postDataByteArrayImage = new ByteArrayOutputStream();
    byte[] data;
    String boundry = "----------V2ymHFg03ehbqgZCaKO6jy";
    try {
        if (!url.startsWith("/")) {
            url = "/" + url;
        }
        String uri = Control.URL_Secure + Control.dtserver + ":"
                + Control.port + url;
        ByteArrayOutputStream postDataByteArray = new ByteArrayOutputStream();

        params.put("sessionId", Control.sessionId);

        if (method.equals("GET")) {
            uri = uri + "?";
            Enumeration enumParams = params.keys();
            while (enumParams.hasMoreElements()) {
                if (!uri.endsWith("?")) {
                    uri = uri + "&";
                }
                String key = (String) enumParams.nextElement();
                uri = uri
                        + key
                        + "="
                        + java.net.URLEncoder.encode((String) params
                                .get(key));

            }
        } else if (method.equals("POST")) {
            Enumeration enumParams = params.keys();
            postDataByteArray.write(("--").getBytes());
            postDataByteArray.write((boundry).getBytes());
            postDataByteArray.write(("\r\n").getBytes());
            while (enumParams.hasMoreElements()) {
                String key = (String) enumParams.nextElement();
                if (!key.equals("image")){
                    postDataByteArray
                            .write(("Content-Disposition: form-data; name=\"")
                                    .getBytes());
                    postDataByteArray.write((key).getBytes());
                    postDataByteArray.write(("\"").getBytes());
                    postDataByteArray.write(("\r\n\r\n").getBytes());
                    postDataByteArray.write(((String) params.get(key))
                            .getBytes());
                    postDataByteArray.write(("\r\n").getBytes());
                    postDataByteArray.write(("--").getBytes());
                    postDataByteArray.write(boundry.getBytes());
                    postDataByteArray.write(("\r\n").getBytes());
                }
            }
            postDataByteArray.close();

        }
        Log.i("URL", uri);
        URL urltoConenct = new URL(uri);
        URLConnection connection = urltoConenct.openConnection();
        HttpURLConnection urlConnection = (HttpURLConnection) connection;

        URLConnection.setDefaultRequestProperty("Method", method); // default
        urlConnection.setRequestProperty("User-Agent", "Android");
        if (method.equals("POST")) {
            urlConnection.setDoOutput(true);
            urlConnection.setFixedLengthStreamingMode(postDataByteArray.toByteArray().length + postDataByteArrayImage.toByteArray().length);
            urlConnection.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + boundry);
            out = urlConnection.getOutputStream();
            out.write(postDataByteArray.toByteArray());
            out.write(postDataByteArrayImage.toByteArray());
            out.close();
        }
        int response = 0;
        try {
            response = urlConnection.getResponseCode();
        } catch (IOException e) {
            if (e.toString()
                    .equals("java.io.IOException: Received authentication challenge is null"))
                throw new RESTException(401, "Invalid Phone or Pin");
            else
                throw e;
        }

        if (response == HttpURLConnection.HTTP_OK) {

            is = urlConnection.getInputStream();
            if (is == null) {
                return new IOException(
                        "Cannot open HTTP InputStream, aborting");
            }

            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            int ch;
            int count = 0;

            while ((ch = is.read()) != -1) {
                bo.write(ch);
                count++;

            }
            data = bo.toByteArray();

            return new String(data);
        } else if (response == 500) {
            return new RESTException(500, "Internal server error");
        } else {
            RESTException x = new RESTException();
            x.setCode(response);
            try {
                is = urlConnection.getInputStream();
                if (is == null) {
                    x.setMessage("Unable to retrieve message");
                    return x;
                }

                ByteArrayOutputStream bo = new ByteArrayOutputStream();
                int ch;
                int count = 0;

                while ((ch = is.read()) != -1) {
                    bo.write(ch);
                    count++;
                }
                data = bo.toByteArray();

                String output = new String(data);
                JSONObject obj;

                try {

                    obj = new JSONObject(output);
                    JSONObject err = obj.getJSONArray("errors")
                            .getJSONObject(0);
                    x.setMessage(err.getString("message"));
                } catch (JSONException e) {
                    Log.e("stuff", output);
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (FileNotFoundException e) {
                // Damn you android! I'm using a REST service here, stop
                // trying to interpret my errors!
                x.setMessage("Unable to retrieve message");
            }
            return x;
        }
    } catch (Exception x) {
        x.printStackTrace();
        /*
         * if (!retried && x.toString().equals(
         * "java.io.IOException: Persistent connection dropped after first chunk sent, cannot retry"
         * )) { retry = true; } if (!retry) { return x; }
         */
        return x;
    } finally {
        try {
            out.close();
        } catch (Exception x) {

        }
        try {
            is.close();
        } catch (Exception x) {

        }
        try {
            c.close();
        } catch (Exception x) {

        }
        params.clear();

    }

    // return null;
  }
4

1 回答 1

0

经过很长时间的挫折,我们发现即使您手动调用连接上的 .close(),Android 也会尝试保持连接处于活动状态。这对我们的 GET 方法很有效,但是 POST 方法使套接字处于无法处理 GET 的状态。添加以下内容解决了我们所有的问题:

urlConnection.setRequestProperty("connection", "close");
于 2012-11-19T13:10:53.690 回答