Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android OKhttp:SSLProtocolException:SSL握手终止_Android_Ssl_Okhttp_Okhttp3 - Fatal编程技术网

Android OKhttp:SSLProtocolException:SSL握手终止

Android OKhttp:SSLProtocolException:SSL握手终止,android,ssl,okhttp,okhttp3,Android,Ssl,Okhttp,Okhttp3,我想知道为什么有时候我会犯这个错误 javax.net.ssl.SSLProtocolException:终止ssl握手: ssl=0x60d46c90:ssl库中出现故障,通常是协议错误 错误:1409443E:SSL例程:SSL3_读取字节:tlsv1警报不适当 回退(外部/openssl/ssl/s3_pkt.c:1256 0x60d57f40:0x00000003) 发出此请求的代码: private <T> void send(final String url, fina

我想知道为什么有时候我会犯这个错误

javax.net.ssl.SSLProtocolException:终止ssl握手: ssl=0x60d46c90:ssl库中出现故障,通常是协议错误 错误:1409443E:SSL例程:SSL3_读取字节:tlsv1警报不适当 回退(外部/openssl/ssl/s3_pkt.c:1256 0x60d57f40:0x00000003)

发出此请求的代码:

private <T> void send(final String url, final Map<String, String> args, 
    final RequestCallback<T> callback, final Parser<T> pParser, 
    final Context pContext, final HTTP_METHOD method, 
    final Map<String, String> headers, final BODY_TYPE bodyType) {

    final Request.Builder builder = getBuilder(url);
    populateHeaders(builder, headers);
    final RequestBody body = getBody(args, bodyType);

    if(method==HTTP_METHOD.POST) {
        builder.post(body);
    } else if(method==HTTP_METHOD.GET) {
        builder.get();
    } else if(method==HTTP_METHOD.PUT) {
        builder.put(body);
    } else if(method==HTTP_METHOD.PATCH) {
        builder.patch(body);
    } else {
        throw new RuntimeException("Please specify correct method name!");
    }

    Request request = builder.build();
    debugRequest(request, whoCalledThisMethod());
    call = client.newCall(request);
    call.enqueue(new StandardRequestCallback(pContext, callback, pParser));
}

这不是一个解决方案,但在涉及上述问题时提供了一些网络调试

如果是上面第1940期中提到的网络接口问题,那么您可以通过实现Dns接口和socketFactory来解决该问题。它可能是你得到了两个DNS记录,一个为你工作,另一个不工作,它会在重启后改变

尝试通过添加调试来确认,查看

Dns.SYSTEM.lookup(主机名)

NetworkInterface.getByInetAddress(地址)

NetworkInterface.getNetworkInterfaces()


更新

Callback.on中的代码调试此问题失败:

@Override
public void onFailure(final Call call, final IOException e) {
    if (call.isCanceled()) {
        SLog.w(TAG, "onFailure: Canceled");
        return;
    }

    if(e instanceof SSLException){

        try {
            Log.d(getClass().getSimpleName(), "Checking DNS hosts ... ");
            List<InetAddress> list = Dns.SYSTEM.lookup(call.request().url().host());
            Log.d(getClass().getSimpleName(), "Number of Entries: "+list.size());
            for (InetAddress address : list) {
                Log.d(getClass().getSimpleName(), address.toString());
            }
            Log.d(getClass().getSimpleName(), "End of Checking DNS hosts");

        } catch (UnknownHostException e1) {
            e1.printStackTrace();
        }


        try {
            Log.d(getClass().getSimpleName(), "Checking Network Interfaces ... ");
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            ArrayList<NetworkInterface> list = Collections.list(interfaces);
            Log.d(getClass().getSimpleName(), "Number of Entries: "+list.size());
            for(NetworkInterface netintface : list) {
                Log.d(getClass().getSimpleName(), netintface.toString());
                List<InterfaceAddress> listaddresses = netintface.getInterfaceAddresses();
                Log.d(getClass().getSimpleName(), "   Number of Interface Addresses: "+listaddresses.size());
                for (InterfaceAddress infcaddress : listaddresses) {
                    Log.d(getClass().getSimpleName(), "   > InterfaceAddress : "+infcaddress.toString());
                }
            }
            Log.d(getClass().getSimpleName(), "End of Checking Network Interfaces");
        } catch (SocketException e1) {
            e1.printStackTrace();
        }


    }
}

我找到了一个解决办法——基本上你可以创建一个新的OkHttpClient实例!请参阅下面的代码

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.IOException;

import javax.net.ssl.SSLException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class ActivityMain extends AppCompatActivity
{
    private Button buttonStart;
    private Button buttonStop;
    private TextView textView;
    private Handler handler;

    private Integer mCount = 0;
    private Boolean mQuit;
    private OkHttpClient client = new OkHttpClient();
    private Runnable mRunnable;

    final int DELAY_SUBSEQUENT_REQUEST = 5000;//5sec
    final String REQUEST_URL = "https://whatever.com/url/to/test";



    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        handler = new Handler();

        buttonStart = (Button)findViewById(R.id.buttonstart);
        buttonStop = (Button)findViewById(R.id.buttonstop);
        textView = (TextView)findViewById(R.id.textview);

        mRunnable = new Runnable() {
            @Override
            public void run() {
                if (!mQuit) {
                    mCount++;
                    textView.setText(String.valueOf(mCount));

                    // do the GET call here
                    RequestGet();
                }
            }
        };

        buttonStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                buttonStart.setEnabled(false);
                triggerDelayedSslRequest(0);
                mQuit = false;
            }
        });

        buttonStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                buttonStart.setEnabled(true);
                mQuit = true;
                handler.removeCallbacks(mRunnable);
                mCount = 0;
            }
        });
    }

    private void triggerDelayedSslRequest(int delay)
    {
        handler.postDelayed(mRunnable, delay);
    }

    private void RequestGet()
    {
        Request request = new Request.Builder()
                .url(REQUEST_URL)
                .build();

        // NOTE: onFailure and onResponse are not on the main thread
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                // the SSL error is trapped here
                e.printStackTrace();

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText(e.getMessage());
                        buttonStart.setEnabled(true);
                    }
                });

                // Crazy "fix" for SSLException
                if(e instanceof SSLException) {
                    client = new OkHttpClient();
                }
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                if (!response.isSuccessful())
                {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            textView.setText("Error Response: "+response.toString());
                        }
                    });
                } else {
                    System.out.println(response.body().string());
                }

                // schedule the next GET request
                triggerDelayedSslRequest(DELAY_SUBSEQUENT_REQUEST);
            }
        });
    }
}


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="a.b.ssltestapp.ActivityMain">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start"
        android:id="@+id/buttonstart"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop"
        android:id="@+id/buttonstop"
        android:layout_below="@+id/buttonstart"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textview"
        android:layout_marginTop="100dp"
        android:text="Press START to test SSL"
        android:gravity="center"
        android:layout_below="@+id/buttonstop"
        android:layout_centerHorizontal="true"/>


</RelativeLayout>
导入android.os.Handler;
导入android.support.v7.app.AppActivity;
导入android.os.Bundle;
导入android.view.view;
导入android.widget.Button;
导入android.widget.TextView;
导入java.io.IOException;
导入javax.net.ssl.SSLException;
导入okhttp3.Call;
导入okhttp3.Callback;
导入okhttp3.OkHttpClient;
导入okhttp3.请求;
导入okhttp3.响应;
公共类活动Main扩展了AppCompatActivity
{
私人按钮启动;
私人按钮按钮;
私有文本视图文本视图;
私人经办人;
私有整数mCount=0;
私有布尔mQuit;
私有OkHttpClient客户端=新OkHttpClient();
私人可运行的mRunnable;
最终整数延迟\后续\请求=5000;//5秒
最终字符串请求\u URL=”https://whatever.com/url/to/test";
@凌驾
创建时受保护的void(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler=新的handler();
buttonStart=(按钮)findViewById(R.id.buttonStart);
buttonStop=(按钮)findViewById(R.id.buttonStop);
textView=(textView)findViewById(R.id.textView);
mRunnable=newrunnable(){
@凌驾
公开募捐{
if(!mQuit){
mCount++;
textView.setText(String.valueOf(mCount));
//在这里接电话吗
RequestGet();
}
}
};
buttonStart.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
buttonStart.setEnabled(false);
triggerDelayedSslRequest(0);
mQuit=false;
}
});
buttonStop.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
buttonStart.setEnabled(true);
mQuit=true;
handler.removeCallbacks(mRunnable);
mCount=0;
}
});
}
私有无效触发器延迟SSLRRequest(整数延迟)
{
handler.postDelayed(mRunnable,delay);
}
私有void RequestGet()
{
Request Request=newrequest.Builder()
.url(请求url)
.build();
//注意:onFailure和onResponse不在主线程上
client.newCall(request).enqueue(new Callback()){
@凌驾
公共void onFailure(调用,最终IOE异常){
//SSL错误被捕获在这里
e、 printStackTrace();
handler.post(新的Runnable(){
@凌驾
公开募捐{
setText(例如getMessage());
buttonStart.setEnabled(true);
}
});
//SSLException的疯狂“修复”
if(SSLexException的实例){
client=new-OkHttpClient();
}
}
@凌驾
public void onResponse(调用、最终响应)引发IOException{
如果(!response.issusccessful())
{
handler.post(新的Runnable(){
@凌驾
公开募捐{
setText(“错误响应:+Response.toString());
}
});
}否则{
System.out.println(response.body().string());
}
//安排下一个GET请求
TriggerDelayedSSLRRequest(延迟后续请求);
}
});
}
}
但是,此修复非常不方便

总结修复方法:

private <T> void send(final String url, final Map<String, String> args, 
    final RequestCallback<T> callback, final Parser<T> pParser, 
    final Context pContext, final HTTP_METHOD method, 
    final Map<String, String> headers, final BODY_TYPE bodyType) {

    final Request.Builder builder = getBuilder(url);
    populateHeaders(builder, headers);
    final RequestBody body = getBody(args, bodyType);

    if(method==HTTP_METHOD.POST) {
        builder.post(body);
    } else if(method==HTTP_METHOD.GET) {
        builder.get();
    } else if(method==HTTP_METHOD.PUT) {
        builder.put(body);
    } else if(method==HTTP_METHOD.PATCH) {
        builder.patch(body);
    } else {
        throw new RuntimeException("Please specify correct method name!");
    }

    Request request = builder.build();
    debugRequest(request, whoCalledThisMethod());
    call = client.newCall(request);
    call.enqueue(new StandardRequestCallback(pContext, callback, pParser));
}
  • 启动该应用程序,让它保持20分钟(也许在这一点上关闭并重新打开wifi?我相信在工作中,情况就是这样)
  • 现在按下应用程序中的开始按钮
  • 观察SSL握手异常(此时将创建一个新的OkHttpClient实例)
  • 再按一下开始按钮
  • 请注意,GET请求现在已成功

创建新的OkHttpClient对象以使SSL握手再次工作是什么原因?

注意:ANDROID 4.4.4 OkHttp:IMO中存在已知错误,可能您的网络连接有时很差,从而导致此问题。此外,您是否尝试过其他Android API?
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.IOException;

import javax.net.ssl.SSLException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class ActivityMain extends AppCompatActivity
{
    private Button buttonStart;
    private Button buttonStop;
    private TextView textView;
    private Handler handler;

    private Integer mCount = 0;
    private Boolean mQuit;
    private OkHttpClient client = new OkHttpClient();
    private Runnable mRunnable;

    final int DELAY_SUBSEQUENT_REQUEST = 5000;//5sec
    final String REQUEST_URL = "https://whatever.com/url/to/test";



    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        handler = new Handler();

        buttonStart = (Button)findViewById(R.id.buttonstart);
        buttonStop = (Button)findViewById(R.id.buttonstop);
        textView = (TextView)findViewById(R.id.textview);

        mRunnable = new Runnable() {
            @Override
            public void run() {
                if (!mQuit) {
                    mCount++;
                    textView.setText(String.valueOf(mCount));

                    // do the GET call here
                    RequestGet();
                }
            }
        };

        buttonStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                buttonStart.setEnabled(false);
                triggerDelayedSslRequest(0);
                mQuit = false;
            }
        });

        buttonStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                buttonStart.setEnabled(true);
                mQuit = true;
                handler.removeCallbacks(mRunnable);
                mCount = 0;
            }
        });
    }

    private void triggerDelayedSslRequest(int delay)
    {
        handler.postDelayed(mRunnable, delay);
    }

    private void RequestGet()
    {
        Request request = new Request.Builder()
                .url(REQUEST_URL)
                .build();

        // NOTE: onFailure and onResponse are not on the main thread
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                // the SSL error is trapped here
                e.printStackTrace();

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText(e.getMessage());
                        buttonStart.setEnabled(true);
                    }
                });

                // Crazy "fix" for SSLException
                if(e instanceof SSLException) {
                    client = new OkHttpClient();
                }
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                if (!response.isSuccessful())
                {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            textView.setText("Error Response: "+response.toString());
                        }
                    });
                } else {
                    System.out.println(response.body().string());
                }

                // schedule the next GET request
                triggerDelayedSslRequest(DELAY_SUBSEQUENT_REQUEST);
            }
        });
    }
}


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="a.b.ssltestapp.ActivityMain">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start"
        android:id="@+id/buttonstart"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop"
        android:id="@+id/buttonstop"
        android:layout_below="@+id/buttonstart"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textview"
        android:layout_marginTop="100dp"
        android:text="Press START to test SSL"
        android:gravity="center"
        android:layout_below="@+id/buttonstop"
        android:layout_centerHorizontal="true"/>


</RelativeLayout>