2012-02-16 5 views
0

Я пишу приложение для Android, которое инициализирует DatagramSocket для подключения к серверу, а затем использует бесконечный цикл для периодического (например, каждые 5 секунд) отправки пакетов данных. Код отправки ниже:Точное обнаружение сбоев отправки сокетов в Java

DatagramPacket packet = new DatagramPacket(message, message.length); 
try { 
    socket.send(packet); 
} 
catch (IOException e) { 
    // Log failure and return 
} 
// Log success 

Теперь я могу позволить себе потерять пакет каждый раз в то время. Но я хотел бы иметь возможность определить, будет ли сервер недоступен (например, сбои), пока я подключен, и в этом случае я хотел бы сохранить сообщения, которые я отправляю (отправить их в другое время). Первоначально я думал, что исключение будет бросаться каждый раз, когда я пытаюсь отправить пакет через этот сокет, и, следовательно, будет иметь дело с хранением сообщений в моем блоке catch. На самом деле это частично работает. Я моделирую серверные сбои, просто отключив сервер, и я начинаю получать исключения с сообщением sendto failed: ECONNREFUSED (Connection refused) при отправке пакета. Проблема заключается в том, не каждая попытка отправить сгенерирует исключение, но только каждая даже попытка - так мой журнал выглядит

Успех, Ошибка, Успех, ошибка, ...

Что происходит в я понимаю, что при первой попытке отправить пакет после того, как сервер становится недоступным, пакет отправляется, сокет не ждет, чтобы увидеть, есть ли сообщение об ошибке, и успешно зарегистрирован. Затем при следующей попытке сокет пытается отправить пакет, видит предыдущее сообщение об ошибке и выдает исключение без отправки пакета, что приводит к регистрации ошибки. Однако, поскольку пакет не был отправлен, снова не будет исключений, возникших при последующей попытке отправить пакет. Это гипотеза, которую я рисовал, увидев мой журнал, поэтому я мог ошибаться в своих рассуждениях здесь.

Мой вопрос в том, есть ли способ убедиться, что исключение бросается каждый раз, пока сервер недоступен? Или есть ли другой способ обнаружить, что другой конец сокета отключен? Я попытался проверить socket.isConnected() внутри моего цикла, но он всегда возвращает true.

+0

, пожалуйста, отправьте код сервера. –

+0

@MisterSmith Почему код сервера имеет значение? Мое намерение - обработать случай, когда сервер недоступен. – Artyom

+0

Потому что я предполагаю, что ваш сервер порождает поток на входящее соединение. –

ответ

3

DatagramSocket по определению connection-less - вот хорошая страница о differences between UDP and TCP для потомков. То, что вы получаете какие-либо ошибки, указывает на то, что вы отправляете на сервер в своей локальной сети, который не отвечает на арпы - либо что наш шлюз по умолчанию уходит, что менее вероятно. То, что любое из ваших сообщений send возвращает ошибки, - очень Не следует полагаться на ОС и сети и ИМО. Это также означает, что если вы поместите маршрутизатор между вами и сервером, то ни один из методов send не вернет мне ошибку.

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

Конечно, как только вы начнете с этой дороги, вам может потребоваться использовать Jgroups или переключиться на TCP/IP. :-)

+0

True. Я попытался ввести какой-то случайный IP-адрес и номер порта для своего приложения, и ожидаемо не получил сообщений об ошибках. Таким образом, это ожидаемое поведение. В самом деле, я получал ошибки, о которых говорю, потому что я запускал сервер на той же машине, что и эмулятор Android с приложением! Я полагаю, единственный способ преодолеть это, не переключаясь на TCP (мне действительно не нужны все накладные расходы), чтобы убедиться, что сервер всегда в порядке. – Artyom

Смежные вопросы