http请求正常,但频繁更改https请求SocketTimeoutException

时间:2018-06-26 08:02:05

标签: java https okhttp socket-timeout-exception

我最近试图将http更改为https,但是由于更改为https后频繁出现请求超时,结果并没有那么高兴,这给我带来了非常糟糕的用户体验。我当前的解决方案是使用线程池执行okhttp同步请求,这对于http请求是正常的。我想要一个解决方案,谢谢!

第一步:初始化okhttpclient

public partial class Form1 : Form
{
    public Process P;
    public IntPtr WindowHandle;
    public Image TargetButton;

    public Form1()
    {
        InitializeComponent();

        Init();
    }

    private void Init()
    {
        TargetButton = Bitmap.FromFile("Bucket.JPG");

        P = Process.Start("C:\\Windows\\System32\\mspaint.exe");
        WindowHandle = P.MainWindowHandle;

        // now to find that button and click it, I have the button stored as image in TargetButton variable above
    }
}

第二步:创建线程池

 public static class MyHttpUtils{
    private static  MyHttpUtils myHttpUtils;

    private OkHttpClient okHttpClient;

    private MyHttpUtils(){
        initClient();
    }

    private void initClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.writeTimeout(60_000, TimeUnit.MILLISECONDS);
        builder.connectTimeout(60_000,TimeUnit.MILLISECONDS);
        builder.readTimeout(60_000,TimeUnit.MILLISECONDS);
        HttpsUtils httpsUtils = HttpsUtils.getInstance();

        HttpsUtils.SSLParams sslParams = httpsUtils.getSslSocketFactory();
        builder.sslSocketFactory(sslParams.sSLSocketFactory,sslParams.trustManager)
                .hostnameVerifier(httpsUtils.hostnameVerifier());//check hostname
        okHttpClient = builder.build();
    }


    public static MyHttpUtils getInstance(){
        if(myHttpUtils == null){
            synchronized (MyHttpUtils.class){
                if(myHttpUtils == null){
                    myHttpUtils = new MyHttpUtils();
                }
            }
        }
        return  myHttpUtils;
    }

    public OkHttpClient getOkHttpClient() {
        return okHttpClient;
    }
}

第三步:创建Runnable

public static class  ThreadPool{
    private static  ThreadPool threadPool = new ThreadPool();

    private ExecutorService service = new ThreadPoolExecutor(0 /* corePoolSize */,
            Integer.MAX_VALUE /* maximumPoolSize */, 60L /* keepAliveTime */, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp ConnectionPool", true));

    public static ThreadPool getInstance(){
        return threadPool;
    }

    public void  execute(Runnable runnable){
        service.execute(runnable);
    }
}

第四步:发送请求

private Runnable  createRunnable(){
   return new Runnable() {
       @Override
       public void run() {

           try {
               okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();
               requestBuilder.url(url).tag(this).build();
               okhttp3.Request request = requestBuilder.build();
               okhttp3.Response response = client.newCall(request).execute();
               if(response.code() == 200){
                  synchronized (this){
                      successSum++;
                  }
                   Log.e(MainActivity.class.getSimpleName(),"success="+successSum);
                   Log.e("myResult","result="+response.body().string());
               }else{
                  synchronized (this){
                      failSum++;
                  }
                   Log.e(MainActivity.class.getSimpleName(),"failSum="+failSum+"==code="+response.code());
               }
           } catch (IOException e) {
               client.connectionPool().evictAll();
              synchronized (this){
                  exceptionSum++;
              }
               Log.e(MainActivity.class.getSimpleName(),"exceptionSum="+exceptionSum+"==msg="+ e.toString());
           }
       }
   };
}

方法:requestSync()

@Override
public void onClick(View view) {
    switch (view.getId()){
        case R.id.btn_request:
            successSum = 0;
            failSum = 0;
            exceptionSum = 0;
            int i = 10;
            while (i>0){
                requestSync();
                i--;
            }

            break;
    }
}

最终结果:发生SocketTimeoutException enter image description here

我在测试时使用了样本数据,请求成功率约为60%;这个结果使我的应用程序非常不友好,但是我不确定为什么会这样,我希望得到一个解决方案,谢谢

1 个答案:

答案 0 :(得分:0)

此问题已解决。因为使用了同步模式请求,所以在发生握手时,ssl将阻止其他线程连接到主机。解决方案是直接将同步模式更改为异步模式。