java的okhttp3库中,客户端如何开启http2协议支持

新手上路,请多包涵

题目描述

我在实现向苹果的APNs进行推送的工作,因为APNs需要http2协议,所以我在代码中使用了okhttp3这个库来提供客户端的http2支持。okhttp3是3.14.0版本。
但当我使用

response = client.newCall(request).execute() 

这个同步方法向APNs发送POST数据时,遇到了 java.io.IOException: unexpected end of stream on https://api.development.push....
的异常。

题目来源及自己的思路

我根据在网上搜索的一些方法尝试了不同的参数或配置,但是都没有效果。
经过分析异常初步觉得是APNs返回http2数据,但是客户端默认使用的还是HTTP1.1,导致库读取reponse时用的还是HTTP1.1的相关类和方法,按HTTP1.1的格式去读取HeaderLine而引发了异常。

我尝试的一些配置代码如下:
1.配置H2协议

OkHttpClient.Builder builder = new OkHttpClient.Builder();
List<Protocol> protocols = new ArrayList<>();
// protocols.add(Protocol.H2_PRIOR_KNOWLEDGE);
protocols.add(Protocol.HTTP_2);
protocols.add(Protocol.HTTP_1_1);
builder.protocols(protocols);

2.开启连接重试

builder.retryOnConnectionFailure(true); 

3.配置协议升级的头字段

Request.Builder rb = new Request.Builder();
rb.addHeader("Connection", "Upgrade, HTTP2-Settings").addHeader("Upgrade", "h2c");

4.减小连接keepalive时间

builder.connectionPool(new ConnectionPool(10, 30, TimeUnit.SECONDS));

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)
下面是异常信息:

java.io.IOException: unexpected end of stream on https://api.development.push.apple.com/...
NotificationResponse{error=null, httpStatusCode=-1, responseBody='null', cause=java.io.IOException: unexpected end of stream on https://api.development.push.apple.com/...}
at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.java:233)
at okhttp3.internal.connection.Exchange.readResponseHeaders(Exchange.java:115)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:94)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:43)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:221)
at okhttp3.RealCall.execute(RealCall.java:81)
at com.clevertap.apns.clients.SyncOkHttpApnsClient.push(SyncOkHttpApnsClient.java:338)
at com.clevertap.apns.ClientDemo.req_apns(ClientDemo.java:164)
at com.clevertap.apns.ClientDemo.main(ClientDemo.java:185)
Caused by: java.io.EOFException: \n not found: limit=159 content=0000180400000000000001000010000003000003e8000500004000000600001f…
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:240)
at okhttp3.internal.http1.Http1ExchangeCodec.readHeaderLine(Http1ExchangeCodec.java:238)
at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.java:213)
... 19 more


你期待的结果是什么?实际看到的错误信息又是什么?

请问OKHTTP中如何开启对HTTP2的支持?或者请问我这个异常的真实原因是什么,又如何解决呢?
请不吝指点,非常感谢。

阅读 6.3k
1 个回答
新手上路,请多包涵

你好,我也碰到这个相同的问题,请问你最终是什么处理的?谢谢

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题