java.net.SocketException: Software caused connection abort: recv failed

之前写的https请求莫名其妙报了这个错误,之前是没有一点问题的啊。代码如下

public static String doPost(String url, Map<String, String> paramsMap) {
try {
DefaultHttpClient client =null;
//支持https
if(url.startsWith("https")){
client= new SSLClient();
}else{
client = new DefaultHttpClient();
}

HttpPost httppost = new HttpPost(url);

String userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36";
httppost.setHeader("User-Agent", userAgent);

// 设置参数
if (paramsMap != null) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
for (String key : paramsMap.keySet()) {
params.add(new BasicNameValuePair(key, paramsMap.get(key)));
}
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
}
// 发送请求
HttpResponse httpresponse = client.execute(httppost);
HttpEntity entity = httpresponse.getEntity();
return EntityUtils.toString(entity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

//设置信任所有证书

public class SSLClient extends DefaultHttpClient{
public SSLClient() throws Exception{  
        super();  
        SSLContext ctx = SSLContext.getInstance("TLS");  
       //SSLContext ctx = SSLContext.getInstance("SSL");
        X509TrustManager tm = new X509TrustManager() {  
                @Override  
                public void checkClientTrusted(X509Certificate[] chain,  
                        String authType) throws CertificateException {  
                }  
                @Override  
                public void checkServerTrusted(X509Certificate[] chain,  
                        String authType) throws CertificateException {  
                }  
                @Override  
                public X509Certificate[] getAcceptedIssuers() {  
                    return null;  
                }  
        };  
        ctx.init(null, new TrustManager[]{tm}, null);  
        SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  
        ClientConnectionManager ccm = this.getConnectionManager();  
        SchemeRegistry sr = ccm.getSchemeRegistry();  
        sr.register(new Scheme("https", 443, ssf)); 
        
    }  
}

这个方法是公用的,而且用请求工具访问对方提供的URL是可以获取返回结果的,问号脸??

那显然是我这个httpClient请求的问题了,百度看了很多回答也没有一点头绪,最后问了大牛同事看了看说现在的httpClient请求不提倡这么写了

CloseableHttpClient client = HttpClients.createDefault();

CloseableHttpResponse httpresponse = client.execute(httppost);

纳尼?就没有问题了!返回结果了!

原来DefaultHttpClient这个实现类虽然可以继续用,但不在被维护也就是废弃掉了,现在用的是CloseableHttpResponse 这个实现类。

但是为什么会出这个错误呢  可能是它的不稳定性导致的吧 还是不太清楚 问题倒总算是解决了。

我用的是httpClient4.4的jar包 希望大家也采用后一种方法吧。修改后的代码如下:

public static String doPostNew(String url, Map<String, String> paramsMap) {

SSLContext ssl = null;
try {
ssl = createIgnoreVerifySSL();
} catch (KeyManagementException e1) {
e1.printStackTrace();
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}  

       // 设置协议http和https对应的处理socket链接工厂的对象  
       Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()  
          .register("http", PlainConnectionSocketFactory.INSTANCE)  
          .register("https", new SSLConnectionSocketFactory(ssl))  
          .build();  
      
       PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);  
       HttpClients.custom().setConnectionManager(connManager);  
       
   //创建自定义的httpclient对象  
       CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build(); 
       
       try {
       
HttpPost httppost = new HttpPost(url);

String userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36";
httppost.setHeader("User-Agent", userAgent);

// 设置参数
if (paramsMap != null) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
for (String key : paramsMap.keySet()) {
params.add(new BasicNameValuePair(key, paramsMap.get(key)));
}
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
}
// 发送请求
CloseableHttpResponse httpresponse = client.execute(httppost);
HttpEntity entity = httpresponse.getEntity();
return EntityUtils.toString(entity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
finally{
client.getConnectionManager().shutdown();//用完了释放连接
   }
return null;
}

public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {  
   SSLContext sc = SSLContext.getInstance("TLS");  
 
   // 实现一个X509TrustManager接口,用于绕过验证,即信任所有证书
   X509TrustManager trustManager = new X509TrustManager() {  
       public void checkClientTrusted(  
               java.security.cert.X509Certificate[] paramArrayOfX509Certificate,  
               String paramString) throws CertificateException {  
       }  
 
       public void checkServerTrusted(  
               java.security.cert.X509Certificate[] paramArrayOfX509Certificate,  
               String paramString) throws CertificateException {  
       }  
 
       public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
           return null;  
       }  
   };  
 
   sc.init(null, new TrustManager[] { trustManager }, null);  
   return sc;  
}

修改之后上面的问题是解决了,但是另一个URL出现了新问题Host name '' does not match the certificate subject provided by the peer

研究发现原来是对方本来提供的https地址就有问题,如下:


又研究了下,为什么之前不会报错呢?

  SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  

就是在这里初始化SSLSocketFactory的时候会多加一个参数:允许所有Hostname验证。同理:

Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()  
          .register("http", PlainConnectionSocketFactory.INSTANCE)  
          .register("https", new SSLConnectionSocketFactory(ssl,SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER))  
          .build();

问题解决。






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值