Https连接Android

Https连接Android,android,https,Android,Https,我有一个应用程序连接到使用有效证书的web服务。唯一的区别是它是一个通配符SSL 问题是:我有一个 ERROR/NoHttpResponseException(5195): org.apache.http.NoHttpResponseException: The target server failed to respond 当我使用3G时。当在WIFI上工作时,在模拟器上工作时,通过我的手机将模拟器拴在3G上工作。但我手机上的3G应用根本不起作用。在HTC Legend CM7.0.3(2.

我有一个应用程序连接到使用有效证书的web服务。唯一的区别是它是一个通配符SSL

问题是:我有一个

ERROR/NoHttpResponseException(5195): org.apache.http.NoHttpResponseException: The target server failed to respond
当我使用3G时。当在WIFI上工作时,在模拟器上工作时,通过我的手机将模拟器拴在3G上工作。但我手机上的3G应用根本不起作用。在HTC Legend CM7.0.3(2.3.3)和Nexus S 2.3.3两个不同网络(维珍移动加拿大和Fido)上进行测试

我的设备有一个PCAP转储,显示了一些错误,但我不太了解它

确认号:TCP断开。未设置ACK标志时,确认字段为非零

我也试过修复这个。我不知道还能去哪里

顺便说一下,web服务与3G上的浏览器配合使用

我们还将basic auth与HttpRequestInterceptor一起使用

我想这就是我能提供的全部细节。如果还需要别的什么,尽管问吧

这也是相关的,我已经尝试了两种修复方法,它们都不起作用

编辑 我开始认为这可能更适合serverfault.com

这是转储和屏幕截图

编辑2 这是我用来连接到所讨论的web服务的代码

protected HttpEntity sendData(List<NameValuePair> pairs, String method)
            throws ClientProtocolException, IOException,
            AuthenticationException {

        pairs.add(new BasicNameValuePair(KEY_SECURITY, KEY));
        pairs.add(new BasicNameValuePair(LANG_KEY, lang));
        pairs.add(new BasicNameValuePair(OS_KEY, OS));
        pairs.add(new BasicNameValuePair(MODEL_KEY, model));
        pairs.add(new BasicNameValuePair(CARRIER_KEY, carrier));

        DefaultHttpClient client = getClient();

        HttpPost post = new HttpPost();
        try {
            post.setHeader("Content-Type", "application/x-www-form-urlencoded");
            post.setEntity(new UrlEncodedFormEntity(pairs));
        } catch (UnsupportedEncodingException e1) {
            Log.e("UnsupportedEncodingException", e1.toString());
        }

        URI uri = URI.create(method);

        post.setURI(uri);

        client.addRequestInterceptor(preemptiveAuth, 0);

        HttpHost target = new HttpHost(host, port, protocol);
        HttpContext httpContext = new BasicHttpContext();

        HttpResponse response = client.execute(target, post, httpContext);
        int statusCode = response.getStatusLine().getStatusCode();

        if (statusCode == 401) {
            throw new AuthenticationException("Invalid username or password");
        }

        return response.getEntity();
    }
受保护的HttpEntity sendData(列表对、字符串方法)
抛出ClientProtocolException、IOException、,
身份验证异常{
添加(新的BasicNameValuePair(KEY_SECURITY,KEY));
添加(新的BasicNameValuePair(LANG_KEY,LANG));
添加(新的BasicNameValuePair(OS_键,OS));
添加(新的BasicNameValuePair(MODEL_KEY,MODEL));
添加(新的BasicNameValuePair(CARRIER_键,CARRIER));
DefaultHttpClient=getClient();
HttpPost=新的HttpPost();
试一试{
post.setHeader(“内容类型”、“应用程序/x-www-form-urlencoded”);
setEntity(新的UrlEncodedFormEntity(对));
}捕获(不支持DencodingException e1){
Log.e(“UnsupportedEncodingException”,e1.toString());
}
URI=URI.create(方法);
post.setURI(uri);
addRequestInterceptor(preemptiveAuth,0);
HttpHost目标=新的HttpHost(主机、端口、协议);
HttpContext HttpContext=新的BasicHttpContext();
HttpResponse response=client.execute(target、post、httpContext);
int statusCode=response.getStatusLine().getStatusCode();
如果(状态代码==401){
抛出新的AuthenticationException(“无效用户名或密码”);
}
返回response.getEntity();
}

您是否尝试过中提到的解决方案

抄写


我终于解决了这个问题:只是一个HTTP头,在路上被squid服务器处理得很糟糕:

预期:100人继续

android SDK上的DefaultHttpClient似乎默认存在。要解决此问题,只需在代码中添加:

  HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), false);
ArrayList nameValuePairs=新的ArrayList();
nameValuePairs.add(新的基本nameValuePairs(“年份”,“1980”));
//http post
试一试{
HttpClient HttpClient=新的DefaultHttpClient();
HttpPost HttpPost=新的HttpPost(“http://example.com/getAllPeopleBornAfter.php");
setEntity(新的UrlEncodedFormEntity(nameValuePairs));
HttpResponse response=httpclient.execute(httppost);
HttpEntity=response.getEntity();
InputStream=entity.getContent();
}捕获(例外e){
e(“Log_标记”,“http连接错误”+e.toString());
}
//将响应转换为字符串
试一试{
BufferedReader reader=新的BufferedReader(新的InputStreamReader(is,“iso-8859-1”),8;
StringBuilder sb=新的StringBuilder();
字符串行=null;
而((line=reader.readLine())!=null){
sb.附加(第+行“n”);
}
is.close();
结果=sb.toString();
}捕获(例外e){
Log.e(“Log_标记”,“错误转换结果”+e.toString());
}

请参阅http连接的此代码

我们终于找到了问题。这与代码无关

正是反向DNS超时。因为我没有收到来自反向DNS的任何答复,我的apache/ssl会话被提前关闭

通过在根设备上使用谷歌的DNS,它工作了

现在唯一要做的就是修复我们的反向DNS

以下是一个解决方法:

在DefaultHttpClient或AndroidHttpClient实例上调用此方法。它将阻止进行反向DNS查找

private void workAroundReverseDnsBugInHoneycombAndEarlier(HttpClient client) {
    // Android had a bug where HTTPS made reverse DNS lookups (fixed in Ice Cream Sandwich) 
    // http://code.google.com/p/android/issues/detail?id=13117
    SocketFactory socketFactory = new LayeredSocketFactory() {
        SSLSocketFactory delegate = SSLSocketFactory.getSocketFactory();
        @Override public Socket createSocket() throws IOException {
            return delegate.createSocket();
        }
        @Override public Socket connectSocket(Socket sock, String host, int port,
                InetAddress localAddress, int localPort, HttpParams params) throws IOException {
            return delegate.connectSocket(sock, host, port, localAddress, localPort, params);
        }
        @Override public boolean isSecure(Socket sock) throws IllegalArgumentException {
            return delegate.isSecure(sock);
        }
        @Override public Socket createSocket(Socket socket, String host, int port,
                boolean autoClose) throws IOException {
            injectHostname(socket, host);
            return delegate.createSocket(socket, host, port, autoClose);
        }
        private void injectHostname(Socket socket, String host) {
            try {
                Field field = InetAddress.class.getDeclaredField("hostName");
                field.setAccessible(true);
                field.set(socket.getInetAddress(), host);
            } catch (Exception ignored) {
            }
        }
    };
    client.getConnectionManager().getSchemeRegistry()
            .register(new Scheme("https", socketFactory, 443));
}

我在我的问题中发布了3个答案,它们都不起作用,其中之一就是这个。这个解决方案对我不起作用。哦,我一定打开了其他链接,我的朋友。你能添加一些相关代码吗?也许会有帮助。@Nicklas A,添加了一些代码。如果需要一些特定的东西,只需提问。这是非常无用的,因为httpclient.execute()上的代码崩溃。看看我的代码,我设置了它,不管怎样,看看我的答案,它解决了我的问题。它是否影响nio连接?@Kai,不知道,从未用它测试过。
private void workAroundReverseDnsBugInHoneycombAndEarlier(HttpClient client) {
    // Android had a bug where HTTPS made reverse DNS lookups (fixed in Ice Cream Sandwich) 
    // http://code.google.com/p/android/issues/detail?id=13117
    SocketFactory socketFactory = new LayeredSocketFactory() {
        SSLSocketFactory delegate = SSLSocketFactory.getSocketFactory();
        @Override public Socket createSocket() throws IOException {
            return delegate.createSocket();
        }
        @Override public Socket connectSocket(Socket sock, String host, int port,
                InetAddress localAddress, int localPort, HttpParams params) throws IOException {
            return delegate.connectSocket(sock, host, port, localAddress, localPort, params);
        }
        @Override public boolean isSecure(Socket sock) throws IllegalArgumentException {
            return delegate.isSecure(sock);
        }
        @Override public Socket createSocket(Socket socket, String host, int port,
                boolean autoClose) throws IOException {
            injectHostname(socket, host);
            return delegate.createSocket(socket, host, port, autoClose);
        }
        private void injectHostname(Socket socket, String host) {
            try {
                Field field = InetAddress.class.getDeclaredField("hostName");
                field.setAccessible(true);
                field.set(socket.getInetAddress(), host);
            } catch (Exception ignored) {
            }
        }
    };
    client.getConnectionManager().getSchemeRegistry()
            .register(new Scheme("https", socketFactory, 443));
}