我有一个使用的应用程序:
compile 'com.squareup.okhttp3:okhttp:2.7.0'
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0'
compile 'com.squareup.okio:okio:1.6.0'
compile 'com.squareup.retrofit2:retrofit:2.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'
并对服务器进行API REST调用。在OKHttpClient上启用SPDY 3时,会引发错误:
04-08 11:01:22.321 10628-10628/dts W/System.err: java.lang.IllegalArgumentException: protocols doesn't contain http/1.1: [spdy/3.1, h2]
04-08 11:01:22.321 10628-10628/dts W/System.err: at okhttp3.OkHttpClient$Builder.protocols(OkHttpClient.java:672)
我无法在OKHttpClient上找到正确启用SPDY / 3或错误代码的任何内容。目标站点已正确配置SPDY / 3。
我已尝试使用SPDY3,HTTP / 2和SPDY的所有组合的两种协议配置。 HTTP / 1,应用程序在配置HTTP / 1时有效,但如果仅启用SPDY / 3则抛出错误:
okHttpClient = new OkHttpClient.Builder()
// .protocols(Collections.singletonList(Protocol.SPDY_3))
.protocols(Arrays.asList(Protocol.SPDY_3, Protocol.HTTP_2))
.retryOnConnectionFailure(true)
.connectTimeout(25, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(30, 120, TimeUnit.SECONDS))
.connectionSpecs(Collections.singletonList(spec))
.addInterceptor(new AddCookiesInterceptor())
.addInterceptor(new ReceivedCookiesInterceptor())
.cache(new okhttp3.Cache(cacheLocation, (500 * 1024 * 1024)))
.build();
}
我知道有人可能有想法,任何帮助都会非常感激。
答案 0 :(得分:1)
显然,最新版本的OKHttp放弃了对SPDY / 3的支持。选择proto SPDY或HTTP2时会抛出错误代码。该文档指出HTTP1始终需要作为proto,以及之后的其他选择。使用Android 4.1切换到HTTP2,你会发现更多的连接问题(OKHttp / Android)不支持开箱即用的TLS1.2,你必须创建一个自定义的SSLSocketFactory来覆盖默认值(来自{{3 }}):
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory delegate;
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
delegate = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return new String[]{"TLSv1.2", "TLS_RSA_WITH_AES_128_CBC_SHA"};
}
@Override
public String[] getSupportedCipherSuites() {
return new String[]{"TLSv1.2", "TLS_RSA_WITH_AES_128_CBC_SHA"};
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if (socket != null && (socket instanceof SSLSocket)) {
((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"});
}
return socket;
}
}