Intereting Posts
Предупреждение: предупреждение: Поддерживаемая исходная версия 'RELEASE_7' из обработчика аннотаций 'android.arch.lifecycle.LifecycleProcessor' меньше, чем -source '1.8' Вращающийся телефон перезапускает видео на Android Черный цвет – вместо этого прозрачный фон для textview в android Список ActionBar Перемещение перекрывающих фрагментов Получить текст внутри кнопки API Twitter не принимает URL-адрес обратного вызова для Android-приложения Жесты не меняются после замены другими в папках Как выполнить поиск по арабскому тексту в JAVA? Невозможно включить заголовки C ++, такие как вектор в Android NDK Произошел INTERNAL_ERROR, когда requestEmail из GoogleSignInOptions Android Gradle Error – Не удалось вызвать IncrementalTask.taskAction () для задачи: project: mergeDebugResources ' Разница между датчиком ориентации и датчиком магнитного поля на Android? Ошибка градиента – выполнение выполнено для задачи: app: dexDebug ' Файлы android .so не извлекаются в / data / data / <package> / lib Android AlertDialog исключение "Ресурсы $ NotFoundException"

OutputStream.write () успешно, но данные не доставляются

У меня очень странное поведение при записи в сокет. В моем мобильном клиенте я использую сокет, который инициализируется следующим образом:

private void initSocket() { socket = new Socket(); socket.connect(new InetSocketAddress(host, port)); os = new DataOutputStream(socket.getOutputStream()); is = new DataInputStream(socket.getInputStream()); } 

Затем периодически (каждые 60 секунд) я читаю и записываю некоторые данные в этот сокет (код здесь немного упрощен):

 if(!isSocketInitialized()) { initSocket(); } byte[] msg = getMessage(); os.write(msg); os.flush(); int bytesAvailable = is.available( ); if(bytesAvailable>0) { byte[] inputBuffer = new byte[bytesAvailable]; int numRead = is.read(inputBuffer, 0, bytesAvailable); processServerReply(inputBuffer, numRead); } 

И это работает. Но … Иногда (очень редко, может быть, 1 или 2 раза в день) мой сервер не получает данные. Журнал моего клиента выглядит так:

 Written A Written B Written C Written D Written E 

и так далее. Но на стороне сервера это выглядит так:

 Received A Received E 

Записи данных B, C, D не были получены, несмотря на то, что на стороне клиента все данные были отправлены без каких-либо исключений!

Такие промежутки могут быть небольшими (2-3 минуты), что не очень плохо, но иногда они могут быть очень большими (1-2 часа = 60-120 циклов), и это действительно проблема для моих клиентов.

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

У меня есть только журналы, и я не могу воспроизвести эту проблему (но это случается с моим клиентом более одного раза в день), а в журналах иногда я вижу, что соединение нарушено с Исключением: «sendto failed: ECONNRESET (Connection reset by peer )». После этого программа закрывает сокет, повторно инициализирует его:

 // close is.close(); os.close(); socket.close(); // reinitialize initSocket(); 

И пытается записать данные снова, как описано выше. Тогда я вижу проблему: соединение установлено, запись успешна, но НИКАКИЕ ДАННЫЕ не прибыли на сервер!

Может быть, это что-то связано с ECONNRESET, возможно, нет, но я хочу упомянуть об этом, потому что может быть это важно.

Я был бы очень благодарен за любые идеи и советы.

PS Может быть, это играет определенную роль: клиентский код работает на мобильном устройстве Android, которое движется (оно находится в автомобиле). Интернет-соединение устанавливается через GPRS.


UPD: Я могу воспроизвести его! По крайней мере частично (клиент отправляет A, B, C, D, E, а сервер получает только A). Это происходит каждый раз, если:

  1. Соединение установлено, клиент читает и пишет -> OK

  2. Соединение потеряно (я отключил свой WLAN-маршрутизатор :)), я стал IOException, я закрываю потоки и сокет -> OK

  3. Я включаю маршрутизатор, соединение вернулось, я снова инициализирую сокет, программа выполняет write () без исключений, но … на сервер не поступает никаких данных.

BTW, поскольку соединение снова доступно () всегда возвращает 0.

Solutions Collecting From Web of "OutputStream.write () успешно, но данные не доставляются"

Избавьтесь от теста available() . Если сверстник должен ответить, просто прочитайте его. В противном случае иногда вы будете читать ответ, а иногда нет, и вы выйдете из синхронизации. Существует очень мало правильных вариантов использования available() , и это не один из них.

Причиной этого странного поведения было не закрытое сокет на стороне сервера. Я мог бы воспроизвести его с небольшим клиентом и сервером. Оба состоят из нескольких строк кода, которые выполняют следующие действия:

  1. Подключиться к серверу
  2. Имитировать мертвое место (например, отключить WiFi)
  3. Закрыть сокет на стороне клиента
  4. НЕ ЗАКРЫВАЙТЕ сокет на стороне сервера
  5. Включить Wi-Fi
  6. Установить новое соединение с клиентом
  7. Записывать данные в это соединение

Вуаля! Клиент записывает данные без каких-либо ошибок, но сервер их не получает …

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

К сожалению, в моем случае это нежизнеспособно, потому что сервер является запатентованным сторонним программным обеспечением.