timeoutIntervalForRequest NSURLSessionConfiguration не работает с фоновым URLSession - PullRequest
0 голосов
/ 27 июня 2018

Я следовал этому уроку Загрузка файлов в фоновом режиме с помощью URLSessionDownloadTask

А это Apple doc Загрузка файлов в фоновом режиме

Я попытался настроить, потому что у нас есть долго работающий API

let config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).background")
    config.timeoutIntervalForRequest = 120
    config.timeoutIntervalForResource = 180

Но я столкнулся с этой странной проблемой:

Если сервер не отвечает ни одним фрагментом данных, это означает, что

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)

вообще не вызывается.

Приложение прекратит выполнение предыдущего запроса и повторяет новый запрос каждые 66 секунд. Я не знаю, откуда взялась эта цифра, но из моего эксперимента примерно 66 секунд

Если я установлю timeoutIntervalForRequest = 10 достаточно точно, приложение будет повторять запрос каждые 10 секунд, но любая попытка установить его выше 66 секунд не будет работать

Не уверен, что кто-то сталкивался с той же проблемой и нашел решение.

Только 1 примечание: время ожидания истекает через 180 секунд, и приложение перестает повторять новые запросы

1 Ответ

0 голосов
/ 29 июня 2018

Во-первых, это ошибка. Пожалуйста, отправьте его на bugreport.apple.com. Тайм-аут не следует игнорировать, как это. Конечно, есть хороший шанс, что это проблема управления питанием, и она не будет устранена, поэтому я не буду задерживать дыхание.

Во-вторых, вы подходите к проблеме таким образом, что гарантированно вызовет проблемы, даже если ошибка тайм-аута была исправлена. Тот факт, что ваш сервер не отправляет обратно ни одного байта, чтобы поддерживать соединение, является, конечно, причиной, по которой устройство iOS отключается, но даже если вы измените это и заставите его отправлять поддельный заголовок по одному байту за раз каждый пять секунд, пока данные не будут готовы, у вас все еще будут проблемы.

По сути, на мобильном устройстве вы действительно не должны по какой-либо причине держать удаленное соединение открытым для удаленного сервера. Это приводит к значительному расходу батареи, чтобы постоянно поддерживать радио Wi-Fi, а тем более сотовую радиосвязь, и, что еще хуже, такое соединение может прерваться в любое время, когда пользователь выходит из зоны действия, переключает сотовые станции или иным образом теряет связь. Сети дерьмовые - сотовые сети вдвойне.

Гораздо лучший подход для длительной обработки на сервере - сделать это асинхронно:

  • Сделайте запрос к серверу.
  • Пусть сервер отправит вам обратно уникальный идентификатор, связанный с запросом, и, при необходимости, приблизительное время завершения.
  • Дождитесь приблизительного времени завершения, затем спросите сервер, как идут дела (предоставив этот уникальный идентификатор).
  • Продолжайте периодически опрашивать сервер, пока сервер не сообщит, что задание выполнено (или не выполнено).
  • Когда сервер сообщает, что задача выполнена, выполните запрос на получение результатов, а затем запрос на освобождение завершенных результатов.
  • Периодически очищать старые, не собранные результаты на сервере с помощью задания cron или аналогичного.

Такой подход позволяет избежать держать радио горячим в течение нескольких секунд по обе стороны от ваших запросов избирательных исключением, и это делает проблему тайм-аут полностью спорный.

...