4

在大多数情况下,我的 HTTP 请求都可以正常工作。但是,有时它们会挂起。

我使用的代码设置为如果请求成功(响应代码为 200 或 201),则调用 screen.requestSucceeded()。如果请求失败,则调用 screen.requestFailed()。

但是,当请求挂起时,它会在调用上述方法之一之前挂起。我的代码有问题吗?我应该使用某种最佳实践来防止任何挂起吗?

以下是我的代码。我将不胜感激任何帮助。谢谢!

HttpConnection connection = (HttpConnection) Connector.open(url
                    + connectionParameters);

            connection.setRequestMethod(method);
            connection.setRequestProperty("WWW-Authenticate",
                    "OAuth realm=api.netflix.com");
            if (method.equals("POST") && postData != null) {
            connection.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            connection.setRequestProperty("Content-Length", Integer
                    .toString(postData.length));
            OutputStream requestOutput = connection.openOutputStream();
            requestOutput.write(postData);
            requestOutput.close();
        }
            int responseCode = connection.getResponseCode();
            System.out.println("RESPONSE CODE: " + responseCode);
            if (connection instanceof HttpsConnection) {
                HttpsConnection secureConnection = (HttpsConnection) connection;
                String issuer = secureConnection.getSecurityInfo()
                        .getServerCertificate().getIssuer();
                UiApplication.getUiApplication().invokeLater(
                        new DialogRunner(
                                "Secure Connection! Certificate issued by: "
                                        + issuer));

            }

            if (responseCode != 200 && responseCode != 201) {
                screen.requestFailed("Unexpected response code: "
                        + responseCode);
                connection.close();
                return;
            }

            String contentType = connection.getHeaderField("Content-type");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            InputStream responseData = connection.openInputStream();
            byte[] buffer = new byte[20000];
            int bytesRead = 0;
            while ((bytesRead = responseData.read(buffer)) > 0) {
                baos.write(buffer, 0, bytesRead);
            }
            baos.close();
            connection.close();
            screen.requestSucceeded(baos.toByteArray(), contentType);
        } catch (IOException ex) {
            screen.requestFailed(ex.toString());
        }
4

4 回答 4

7

没有任何痕迹,我只是在黑暗中拍摄。

尝试添加这 2 个电话,

System.setProperty("http.keepAlive", "false");

connection.setRequestProperty("Connection", "close");

Keep-alive 是导致连接失效的常见原因。这些调用将禁用它。

于 2010-04-28T23:29:20.610 回答
3

我没有看到代码有任何问题。可能是您的平台存在间歇性错误,或者网站导致连接挂起。更改连接参数(例如保持活动状态)可能会有所帮助。

但是,即使设置了超时,套接字也可以无限期地挂起——几年前,一位朋友通过拔出网络电缆向我恰当地展示了这一点——我的程序只是永远挂在那里,即使将 SO_TIMEOUT 设置为 30 秒。

作为“最佳实践”,您可以通过将所有网络通信移动到单独的线程来避免挂起您的应用程序。如果将每个请求包装为 Runnable 并将它们排队等待执行,则可以保持对超时的控制(同步仍在 java 中,而不是阻塞的本机 I/O 调用)。您可以在(例如)30 秒后中断您的等待线程,以避免停止您的应用程序。然后,您可以通知用户,或重试请求。因为该请求是一个可运行的,您可以将它从停滞线程的队列中移除并安排它在另一个线程上执行。

于 2010-04-28T23:41:35.300 回答
1

我看到您有处理发送“POST”类型请求的代码,但是没有任何东西可以在请求中写入 POST 数据。如果连接类型是“POST”,那么您应该在 connection.getResponseCode() 之前执行以下操作:

  • 设置“内容长度”标头
  • 设置“Content-Type”标题(你正在做的)
  • 使用 connection.openOutputStream() 从连接中获取 OutputStream
  • 将 POST(表单)数据写入 OutputStream
  • 关闭输出流
于 2010-04-29T03:40:55.810 回答
1

我在黑莓 OS 5.0 上也注意到了这个问题。没有办法可靠地重现这一点。我们最终使用了使用等待/通知和 Timertask 的附加线程。

于 2010-11-02T00:30:26.127 回答