Подтвердить что ты не робот

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
4b9b3361

Ответ 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, чтобы обработать это исключение, снова представив его или посмотрите, может ли класс, который вы используете для загрузки, увеличить таймаут для транзакции!