关于使用OkHttpClient进行http请求,抛出IO异常问题

1、如果你没有使用OkHttpClient单例模式的话,而是每次都new 一个OkHttpClient 在大量的请求下,很容易就会出现OOM 因为OkHttpClient 每new 一个 就会创建一个线程池,线程池默认有5个线程,不断new 就会出现OOM

2、在使用OkHttpClient 单例模式的情况下,出现IOException和EOFException 类似如下:

java.io.IOException: unexpected end of stream on Connection{xxx, proxy=DIRECT hostAddress= cipherSuite=none protocol=http/1.1}
    at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:208)
    at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)
    at okhttp3.RealCall.execute(RealCall.java:77)
    at com.wondersgroup.mall.ucenter.common.utils.HttpUtils.syncGet(HttpUtils.java:43)
    at com.wondersgroup.mall.ucenter.common.utils.HttpUtils.main(HttpUtils.java:77)
Caused by: java.io.EOFException: \n not found: limit=0 content=…
    at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:237)
    at okhttp3.internal.http1.Http1Codec.readHeaderLine(Http1Codec.java:215)
    at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189)
    ... 17 more

这种情况是 OkHttpClient 复用了之前的连接,但是服务器已经关闭连接,而出现的异常。简单介绍一下,OkHttpClient 内部维护一个连接池,当你发起一个连接时,如果请求头的connection 是keepAlive 它会维护这个连接在连接池(默认5分钟),并且当有下一次相同的http请求(请求地址相同),就会复用维护在连接池的连接,不会再进行tcp连接,但问题就这,虽然OkHttpClient 连接为5分钟,但一般服务器不会保持一个连接为5分钟,因为那样会很浪费连接,所以当你两次相同请求间隔时间很长,服务器关闭了连接(比如3分钟)就会出现上面的异常,当然如果服务器不关闭连接,那么也就不会出现。

 

在Android 10及以上的版本中,需要在应用程序中使用网络连接时,需要通过网络安全配置文件或使用网络安全API来保护网络连接。下面是一个使用OkHttp库发送HTTP Post请求的示例代码: 首先,需要在你的应用程序模块的build.gradle文件中添加以下依赖: ```groovy implementation 'com.squareup.okhttp3:okhttp:4.9.0' ``` 然后,在你的代码中实现以下代码: ```java import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import java.io.IOException; public class HttpPostExample { public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); OkHttpClient client = new OkHttpClient(); // 在主线程之外执行网络请求 public void run(String url, String json) throws IOException { RequestBody body = RequestBody.create(JSON, json); Request request = new Request.Builder() .url(url) .post(body) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string()); } } } ``` 在这个示例中,我们使用OkHttp库来发送POST请求。首先我们定义了一个MediaType,它表示请求的内容类型。然后我们创建了一个OkHttpClient对象,它将被用于发送请求。在run()方法中,我们创建了一个RequestBody对象,它包含了我们要发送的JSON数据。接下来,我们创建了一个Request对象,将URL和RequestBody设置为POST方法,并使用我们的OkHttpClient对象来执行该请求。最后,我们检查响应是否成功,如果没有成功,则抛出一个IOException异常。如果响应成功,我们将响应体的内容打印到控制台上。 现在,我们可以在我们的应用程序中使用这个类来发送POST请求: ```java try { HttpPostExample example = new HttpPostExample(); String url = "http://your-url.com"; String json = "{\"name\":\"John\", \"age\":30}"; example.run(url, json); } catch (IOException e) { e.printStackTrace(); } ``` 在这个示例中,我们创建了一个HttpPostExample对象,并将URL和JSON数据作为参数传递给run()方法。如果请求成功,服务器将返回响应数据,你可以在自己的应用程序中使用这个数据。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值