Facebook SDK 3 EOFException
Я использую новый FaceBook SDK 3.0. При отправке изображений с URL-адреса на "me/photos" я периодически получаю EOFException
. Я получаю эту ошибку время от времени (~ 1 в 20 раз).
Я также должен добавить, что сразу после получения EOFException
, если я снова отправлю сообщение, он успешно отправляется.
Итак, пока я закодирован, чтобы автоматически повторять попытку еще раз, если я получаю EOFException
, и решение кажется удовлетворительным.
Но мне нужно знать, что вызывает его, это ошибка в Android SDK. Я много думал об этом, но ничего не мог получить.
Я отправляю журналы (удаляя токен доступа и URL-адрес изображения по соображениям безопасности)
06-05 15:09:42.585: D/FacebookSDK.Request(16611): Request:
06-05 15:09:42.585: D/FacebookSDK.Request(16611): Id: 9
06-05 15:09:42.585: D/FacebookSDK.Request(16611): URL:https://graph.facebook.com/me/photos?caption=abc&format=json&sdk=android&migration_bundle=fbsdk%3A20121026&access_token=ADBCEFG&url=http%3A%2F%2Ftest.test.test%2Ftest%2Ftest%2F201695%2Ftest%2F18629
06-05 15:09:42.585: D/FacebookSDK.Request(16611): Method: POST
06-05 15:09:42.585: D/FacebookSDK.Request(16611): User-Agent: FBAndroidSDK.3.0.0
06-05 15:09:42.585: D/FacebookSDK.Request(16611): Content-Type: multipart/form-data; boundary=3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f
06-05 15:09:42.585: D/FacebookSDK.Request(16611): Parameters:
06-05 15:09:42.585: D/FacebookSDK.Request(16611): caption: abc
06-05 15:09:42.585: D/FacebookSDK.Request(16611): format: json
06-05 15:09:42.585: D/FacebookSDK.Request(16611): sdk: android
06-05 15:09:42.585: D/FacebookSDK.Request(16611): migration_bundle: fbsdk:20121026
06-05 15:09:42.585: D/FacebookSDK.Request(16611): access_token: ABCDEF
06-05 15:09:42.585: D/FacebookSDK.Request(16611): url: http://test.test.test/test/test/201695/test/18629
06-05 15:09:42.585: D/FacebookSDK.Request(16611): Attachments:
06-05 15:09:42.600: D/FacebookSDK.Response(16611): Response <Error>: java.io.EOFException
Ответы
Ответ 1
Проблема
Это проблема, связанная с HttpURLConnection
. Фактический сокет, используемый для соединения, выбирается из пула. Большинство серверов создают постоянные соединения (заголовок Connection: Keep-Alive
), чтобы повторно использовать существующие сокеты, которые дешевле, чем создание нового каждый раз. Проблема возникает из-за того, что эти сокеты открыты в течение определенного периода времени, в основном 60 секунд или около того, затем они закрыты и не могут быть повторно использованы. Однако ОС Android пытается использовать один и тот же сокет, поскольку он считает, что сокет по-прежнему хорош, поскольку он был назначен одному и тому же хосту, поэтому он начинает отправлять пакеты, ожидающие ACK и другие пакеты ответов, которые никогда не появляются, поскольку сокет не открылся, хотя ожидал ответа, следовательно EOFException
.
Решение
Шаг 1 - Ограничьте размер пула на относительно небольшое число
private static final int MAX_CONNECTIONS = 5;
// ...
static {
System.setProperty("http.maxConnections", String.valueOf(MAX_CONNECTIONS));
}
Шаг 2 - Реализовать механизм повтора
Если вы используете код Facebook и получаете EOFException
, заверните его в try-catch, который ловит исключение и повторяет подключение к URL-адресу до максимального размера пула. Здесь можно использовать заглушку метода (я не знаю SDK для Facebook, следовательно, TODO
):
private void connect(int retryNumber) {
try {
// TODO your facebook code goes here
} catch (EOFException e) {
if (retryNumber > MAX_CONNECTIONS) {
// TODO handle exception, it over the limit, so it is a different problem
} else {
// TODO disconnect first, if possible
connect(retryNumber + 1);
}
} catch (Exception e) {
// TODO other exception handling
} finally {
// TODO disconnect, if possible
}
}
Конечно, вы должны вызвать этот метод с помощью 0 retryNumber (connect(0);
) в первый раз.
Ответ 2
Похоже, что у вас могут быть проблемы с подключением к Интернету.
Вы можете написать в какой-нибудь retrylogic, чтобы обработать это исключение, снова представив его или посмотрите, может ли класс, который вы используете для загрузки, увеличить таймаут для транзакции!