Что делать, если запрос отправлен на сервер и в ожидании ответа интернет-соединение потеряно?

14

Я отправляю огромное количество данных на сервер. Теперь, когда я отправил данные и жду ответа сервера, внезапно мое устройство Android теряет подключение к Интернету.
Итак, что я делал, это отображал диалоговое окно оповещения о потере соединения, но на стороне сервера данные уже были обработаны и обновлены где-то, например, по любому URL. Но мой телефон Android не знает этого, так как он никогда не получал ответ. Как это решить.
Может ли это быть сделано на стороне сервера или на самом Android Как?
Как сервер узнает, что телефон Android не будет слушать ответ?
Это может быть перспектива оптимизации взаимодействия клиент-сервер.

mayank_droid
источник
Сколько данных мы говорим? Гигабайт?
Даниэль Холлинрейк,
Не так много 7-8 МБ, но время отклика сервера слишком велико, а скорость загрузки с телефона составляет около 128 КБ / с. Я не говорю о размере данных, но проблема подключения.
mayank_droid

Ответы:

15

Это довольно распространенная проблема с асинхронными транзакциями, которая состоит из нескольких частей.

  1. Как обе стороны узнают, что запрос на транзакцию был успешно получен?
  2. Как вы повторно отправляете запрос транзакции, который, по мнению клиента, не был получен должным образом?
  3. Как сервер обнаруживает повторные запросы от клиента, когда сервер успешно получил первый запрос?
  4. Как клиент узнает, где получить результаты транзакции?

Самое замечательное в HTTP заключается в том, что все эти проблемы довольно легко решить.

Представьте себе структуру URL следующим образом:

POST http://my.server.com/application/engine/queue 
GET   http://my.server.com/application/engine/results?jobid=43425

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

Клиент получает результаты запроса из URL-адреса результатов. Этот вызов может повторяться так часто, как это необходимо для получения результатов. Если он вызывается до того, как результаты станут доступны, тогда ответом может быть ответ NO-CONTENT, поэтому клиент знает, что сервер распознает идентификатор задания, но еще не имеет содержимого. Если идентификатор задания не распознан, то NOT-FOUND является подходящим ответом.

Конечным результатом является то, что клиент всегда может сделать разумное действие, когда сеть потеряна и восстановлена, а также сервер всегда может разумно обрабатывать запросы от клиента

Майкл Шоу
источник
3
Это или просто выполнение короткого запроса с запросом идентификатора транзакции, затем несколько запросов на добавление данных в транзакцию (здесь можно разделить передачу на более мелкие фрагменты, чтобы получить частичные подтверждения), а затем окончательный запрос «фиксации». После этого вы можете установить разные таймауты для полностью пустых транзакций (клиент, скорее всего, не получил идентификатор), частично загруженных транзакций и результатов (если клиент не получил результаты, он может повторить запрос «commit»).
Саймон Рихтер
Это позволит справиться с ситуацией, когда соединение теряется во время передачи запроса. В ответ на заданный вопрос говорится о потере соединения после отправки данных, но до завершения запроса.
Майкл Шоу
1
Это также обрабатывается. Транзакция commit невелика и использует идентификатор транзакции, поэтому ее можно дешево переиздать без повторной передачи данных, и сервер может либо начать обработку, либо вернуть результат из более раннего вызова. Это очень похоже на то, что вы предлагаете; разница в том, что у меня есть отдельный запрос на создание идентификатора задания, поэтому у меня есть дополнительная точка синхронизации, чтобы клиент мог узнать, существует ли уже задание, без повторной передачи полного запроса.
Саймон Рихтер
да, это имеет смысл.
Майкл Шоу
Таким образом, если транзакция содержит частичные данные на сервере, я знаю, что существует клиент, который знает этот идентификатор и пытается завершить транзакцию, поэтому я могу сохранить частичное состояние и предложить возобновить передачу на полпути, минимизируя требования к пропускной способности и удаляя нужно сравнить содержание запроса, чтобы найти дубликаты.
Саймон Рихтер
4

Это подпадает под основы протокола связи. Клиент Android запросил транзакцию, и Сервер должен выполнить транзакцию. Если транзакция зависит от подтверждения клиента Android, то это вызов ACK / NAK.

ACK (подтверждение) и NAK (отрицательное подтверждение) используются, чтобы сообщить другой стороне результат запроса.

Что вы спрашиваете о типе обмена рукопожатиями между клиентом и сервером, и он может быть выполнен с помощью базового обмена ACK / NAK.

Вот пример загрузки на Android файла с двухсторонним подтверждением.

Android -> upload files -> Server
Android <- ACK #id <- Server
Android -> ACK #id -> Server

В приведенном выше примере я добавил #idуникальный идентификатор для транзакции. Сервер должен получить файлы, создать запись транзакции и отправить ее в ответ на Android. Android должен затем подтвердить эту транзакцию (или, наоборот, NAK для отказа).

Вот пример отключения Android во время рукопожатия.

Android -> upload files -> Server
Android <- ACK #id <- Server
/** no ACK response **/

В приведенном выше примере сервер принял загруженные файлы и отправил #id ответ ACK обратно в Android, но Android никогда не отвечает ACK. Устройство Android не удалось завершить квитирование. Вам решать, как Сервер должен справиться с этим. Удалите транзакцию, сохраните транзакцию и подождите, пока устройство Android не вернется позже или в любом случае завершите транзакцию.

Сервер может предположить, что, поскольку устройство не ответило ACK. Устройство Android не обновило свое внутреннее состояние, чтобы указать, что загрузка прошла успешно. Я бы отменил транзакцию и позволил бы устройству повторить ее в будущем.

Reactgular
источник