[英]Android - ErrnoException: socket failed: EMFILE (Too many open files) when making http requests
In my app I am making http get and http post requests and after about making like 40-50 requests I get the following error exception.在我的应用程序中,我正在发出 http get 和 http post 请求,大约发出 40-50 个请求后,我收到以下错误异常。 It looks like the http connection is keeping too many files open even after making the calls.看起来即使在进行调用之后,http 连接仍然打开了太多文件。 I have added the HTTP Async handlers and their usages at the bottom.我在底部添加了 HTTP 异步处理程序及其用法。 Any suggestions would be highly appreciated.任何建议将不胜感激。 Thanks for your time for reading this.感谢您花时间阅读本文。
10-01 23:08:53.214 30139-30321/com.app W/System.err﹕ org.apache.http.conn.HttpHostConnectException: Connection to http://152.125.228.214:8080 refused
10-01 23:08:53.220 30139-30321/com.app W/System.err﹕ at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:188)
10-01 23:08:53.229 30139-30139/com.app E/SharedPreferencesImpl﹕ Couldn't create directory for SharedPreferences file /data/data/com.app/shared_prefs/MY_SHARED_PREF.xml
10-01 23:08:53.232 30139-30321/com.app W/System.err﹕ at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169)
10-01 23:08:53.232 30139-30321/com.app W/System.err﹕ at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124)
10-01 23:08:53.232 30139-30321/com.app W/System.err﹕ at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365)
10-01 23:08:53.232 30139-30321/com.app W/System.err﹕ at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560)
10-01 23:08:53.232 30139-30321/com.app W/System.err﹕ at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492)
10-01 23:08:53.233 30139-30321/com.app W/System.err﹕ at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470)
10-01 23:08:53.233 30139-30321/com.app W/System.err﹕ at com.app.https.AsyncHttpTask.doInBackground(AsyncHttpTask.java:177)
10-01 23:08:53.233 30139-30321/com.app W/System.err﹕ at com.app.https.AsyncHttpTask.doInBackground(AsyncHttpTask.java:31)
10-01 23:08:53.233 30139-30321/com.app W/System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:292)
10-01 23:08:53.233 30139-30321/com.app W/System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:237)
10-01 23:08:53.233 30139-30321/com.app W/System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
10-01 23:08:53.233 30139-30321/com.app W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
10-01 23:08:53.234 30139-30321/com.app W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
10-01 23:08:53.234 30139-30321/com.app W/System.err﹕ at java.lang.Thread.run(Thread.java:818)
10-01 23:08:53.234 30139-30321/com.app W/System.err﹕ Caused by: java.net.ConnectException: socket failed: EMFILE (Too many open files)
10-01 23:08:53.235 30139-30321/com.app W/System.err﹕ at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:186)
10-01 23:08:53.235 30139-30321/com.app W/System.err﹕ ... 14 more
10-01 23:08:53.235 30139-30321/com.app W/System.err﹕ Caused by: java.net.SocketException: socket failed: EMFILE (Too many open files)
10-01 23:08:53.239 30139-30321/com.app W/System.err﹕ at libcore.io.IoBridge.socket(IoBridge.java:623)
10-01 23:08:53.239 30139-30321/com.app W/System.err﹕ at java.net.PlainSocketImpl.create(PlainSocketImpl.java:198)
10-01 23:08:53.239 30139-30321/com.app W/System.err﹕ at java.net.Socket.checkOpenAndCreate(Socket.java:687)
10-01 23:08:53.240 30139-30321/com.app W/System.err﹕ at java.net.Socket.connect(Socket.java:847)
10-01 23:08:53.240 30139-30321/com.app W/System.err﹕ at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:124)
10-01 23:08:53.240 30139-30321/com.app W/System.err﹕ at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:149)
10-01 23:08:53.240 30139-30321/com.app W/System.err﹕ ... 14 more
10-01 23:08:53.240 30139-30321/com.app W/System.err﹕ Caused by: android.system.ErrnoException: socket failed: EMFILE (Too many open files)
10-01 23:08:53.241 30139-30321/com.app W/System.err﹕ at libcore.io.Posix.socket(Native Method)
10-01 23:08:53.241 30139-30321/com.app W/System.err﹕ at libcore.io.BlockGuardOs.socket(BlockGuardOs.java:282)
10-01 23:08:53.241 30139-30321/com.app W/System.err﹕ at libcore.io.IoBridge.socket(IoBridge.java:608)
10-01 23:08:53.241 30139-30321/com.app W/System.err﹕ ... 19 more
10-01 23:08:53.242 30139-30139/com.app D/com.app.util.JukeSpotUtils﹕ [ 10-01 23:08:54.556 191: 645 I/AudioFlinger ]
BUFFER TIMEOUT: remove(4101) from active list on thread 0xb5ae5008
Following is the code for making the HTTP requests.以下是发出 HTTP 请求的代码。
public class AsyncHttpTask extends AsyncTask<String, Void, Response> {
private HttpHandler httpHandler;
private TaskCallback taskCallback;
private HTTPType httpType;
private String url;
private String json;
private NameValuePair[] headers;
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
public AsyncHttpTask(HttpHandler httpHandler, TaskCallback taskCallback, HTTPType httpType
, String url, String json) {
this.httpHandler = httpHandler;
this.taskCallback = taskCallback;
this.httpType = httpType;
this.url = url;
this.json = json;
}
@Override
protected void onPreExecute() {
if (taskCallback != null) {
taskCallback.onPreExecute();
}
}
@Override
protected Response doInBackground(String... arg0) {
InputStream inputStream = null;
Response responseToReturn = new Response("", 500);
try {
Response response = null;
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 5000);
HttpConnectionParams.setSoTimeout(httpParameters, 10000);
HttpClient httpclient = new DefaultHttpClient(httpParameters);
HttpResponse httpResponse = httpclient.execute(httpHandler.getHttpRequestMethod());
inputStream = httpResponse.getEntity().getContent();
if (inputStream != null) {
response = new Response(convertInputStreamToString(inputStream), httpResponse.getStatusLine().getStatusCode());
} else {
response = new Response("Did not work :(", httpResponse.getStatusLine().getStatusCode());
}
responseToReturn = response;
} catch (Exception e) {
e.printStackTrace();
} finally {
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return responseToReturn;
}
@Override
protected void onPostExecute(Response response) {
if (taskCallback != null) {
taskCallback.onPostExecute();
}
httpHandler.onResponse(response);
}
private String convertInputStreamToString(InputStream inputStream) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
String result = "";
while ((line = bufferedReader.readLine()) != null) {
result += line;
}
return result;
}
}
Following is an Abstract class which I use for defining my own implementation of HTTPGet objects and HTTPPost objects.下面是一个抽象类,我用它来定义我自己的 HTTPGet 对象和 HTTPPost 对象的实现。
public abstract class HttpHandler {
public abstract HttpUriRequest getHttpRequestMethod();
public abstract void onResponse(Response result);
public void execute(TaskCallback taskCallback, HTTPType httpType, String url, String json) {
new AsyncHttpTask(this, taskCallback, httpType, url, json).execute();
}
}
Following is the code for how I use my HttpHandler in the service I wrote.以下是我如何在我编写的服务中使用我的 HttpHandler 的代码。
new HttpHandler() {
@Override
public HttpUriRequest getHttpRequestMethod() {
String refreshUrl = JukeSpotUtils.formRequestUrl(context,
context.getString(R.string.refresh_token_api));
HttpPost httpPost = new HttpPost(refreshUrl);
try {
JSONObject token = new JSONObject();
token.put("refreshToken", getPreferenceValue(context, context.getString(R.string.refresh_token)));
httpPost.setHeader("Content-Type", "application/json");
httpPost.setEntity(new StringEntity(token.toString()));
} catch (Exception e) {
e.printStackTrace();
}
return httpPost;
}
@Override
public void onResponse(Response response) {
if (response != null && response.isSuccessful()) {
try {
flushOldToken(context, response.getResult());
Log.d("ACCESS_TOKEN", getPreferenceValue(context, context.getString(R.string.access_token)));
if (simpleCallback != null) {
simpleCallback.callBack();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.execute(null, HTTPType.POST, true);
either your connections are not closing properly or you have executed many httpHandler simultaneously. 您的连接未正确关闭,或者您同时执行了许多httpHandler。 You can try using threadPoolExecutor to start AsyncTask 您可以尝试使用threadPoolExecutor启动AsyncTask
response.close()
.使用response.close()
关闭您的回复。 We ran into this when doing multi-threaded networking and running into lots of 400
responses (intentional) during this.我们在进行多线程网络时遇到了这个问题,并在此期间遇到了大量400
响应(有意的)。
What fixed it was ensuring that the response
was being closed if it encountered an unsuccessful request, by doing:通过执行以下操作,可以确保在遇到不成功的请求时关闭response
:
response.close()
This must free up the socket immediately as opposed to waiting for some kind of timeout that can be too long and end up using all the file descriptors up before they have a chance to be let go automatically.这必须立即释放套接字,而不是等待某种可能太长的超时并最终在它们有机会自动释放之前使用所有文件描述符。
Read more here:在此处阅读更多信息:
https://square.github.io/okhttp/4.x/okhttp/okhttp3/-response-body/ https://square.github.io/okhttp/4.x/okhttp/okhttp3/-response-body/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.