HttpsURLConnection和间歇性连接

6
我希望有人能够帮助我解决使用HttpsURLConnection代码时遇到的间歇性连接问题。以下是我使用的代码:
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setReadTimeout(10 * 1000); 
if conn.getResponseCode() != 200) { 
            Log.v(TAG, "error code:" + conn.getResponseCode()); 
} 

每次我使用连接来拉取JSON文件时,连接都能正常工作。但是,当我再次使用连接发送命令时,第一次总是失败的。如果我在短时间内(5秒内)发送命令,则通常可以正常工作,但是如果等待一段时间后再发送,则会失败。我认为这不是SSL问题,因为它第一次连接就正确地连接了,但我可能在这里错了。我还尝试了许多不同的变化,例如添加:
conn.setUseCaches(false); 
conn.setRequestProperty("Connection","Keep-Alive"); 
conn.getHostnameVerifier(); 
conn.getSSLSocketFactory(); 
conn.setDoOutput(true); 
conn.setDoInput(true); 
conn.setRequestMethod("POST"); 
conn.wait(100); 

然而,我没有运气。非常感谢您的任何帮助。

如果我可以建议,使用LogCat并在代码块内放置调试语句,以便它可以向您报告失败的确切位置。 - Anthony Forloney
我从conn.getResponseCode()得到的Logcat响应是“-1”,我搜索了一下,没有找到关于https连接的-1响应代码的任何信息。 - OliverPank
3个回答

9
尝试在操作之前使用 System.setProperty("http.keepAlive", "false");,这将有助于避免连接问题。
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

太好了,这个方法可行。我不知道你可以使用“System.”。我猜测SSL连接在之前一直保持打开状态,而我在不同的活动中移动。谢谢! - OliverPank
是的,我认为这与错误流没有完全读取有关。 - m6tt
应该在Froyo版本中得到修复。 - Matt Briançon
没有证书和握手,传输到我的服务器是否安全? - Geek Guy

2
尝试使用以下代码 - 对我来说它非常可靠:
public static final String USER_AGENT = "Mozilla/5.0 (Linux; U; Android 1.1; en-us;dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2";
private DefaultHttpClient getThreadSafeHttpClient() {
    final HttpParams params = new BasicHttpParams();
    params.setParameter("http.useragent", USER_AGENT);
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setContentCharset(params, "UTF-8");
    final SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
    sslSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    registry.register(new Scheme("https", sslSocketFactory, 443));
    final ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, registry);
    final DefaultHttpClient httpclient = new DefaultHttpClient(manager, params);
    // how to handle retries
    final HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
        public boolean retryRequest(final IOException exception, final int executionCount, final HttpContext context) {
            if (executionCount >= 5) {
                // Do not retry if over max retry count
                return false;
            }
            if (exception instanceof NoHttpResponseException) {
                // Retry if the server dropped connection on us
                return true;
            }
            if (exception instanceof SSLHandshakeException) {
                // Do not retry on SSL handshake exception
                return false;
            }
            final HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
            final boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
            if (idempotent) {
                // Retry if the request is considered idempotent
                return true;
            }
            return false;
        }

    };
    httpclient.setHttpRequestRetryHandler(myRetryHandler);
    return httpclient;
}

谢谢...这比我简单的https url连接要复杂得多。我不确定如何确切地使用它。由于getThreadSafeHttpClient函数没有任何输入,我应该在哪里输入我的url? - OliverPank
你只需要使用它来获取 HttpClient,然后像平常一样使用 client。类似这样:HttpClient client = getThreadSafeHttpClient(); - Bostone
HttpGet get = new HttpGet(url);HttpResponse response = this.client.execute(get); - Bostone
DroidIn,您建议即使连接正常工作,也应始终设置SSLSocketFactory和HostnameVerifier吗? - OliverPank
1
如果您确定永远不会使用https,那么您就不必这样做。我只是将此代码作为模板,并在初始化HttpClient时设置一次。 - Bostone

0

仅在m6tt上面的回答中稍作补充:

private static void disableConnectionReuseIfNecessary() {
    // HTTP connection reuse which was buggy pre-froyo
    if (!Constants.SUPPORTS_FROYO) {
        System.setProperty("http.keepAlive", "false");
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接