Как изящно восстановиться после исключения сокета C # udp - PullRequest
10 голосов
/ 10 апреля 2010

Контекст: я портирую приложение Linux Perl на C #, сервер прослушивает порт udp и поддерживает несколько одновременных диалогов с удаленными клиентами через один сокет udp. Во время тестирования я отправляю большие объемы пакетов на сервер udp, случайным образом перезагружая клиентов, чтобы наблюдать, как сервер регистрирует новые соединения. Проблема заключается в следующем: когда я убиваю клиент udp, на сервере все еще могут быть данные, предназначенные для этого клиента. Когда сервер пытается отправить эти данные, он получает сообщение icmp «no service available» и, следовательно, в сокете возникает исключение.

Я не могу повторно использовать этот сокет, когда я пытаюсь связать асинхронный обработчик C # с сокетом, он жалуется на исключение, поэтому мне приходится закрывать и снова открывать сокет udp на порту сервера. Это единственный способ обойти эту проблему? Конечно, есть какой-то способ «исправить» сокет udp, так как технически сокеты UDP не должны знать о состоянии удаленного сокета?

Любая помощь или указатели будут высоко оценены. Спасибо.

1 Ответ

1 голос
/ 10 апреля 2010

Я думаю, что вы правы, говоря: «сервер не должен знать». Если вы отправляете UDP-пакет на какой-либо IP / порт, который может быть или не быть открытым, у сервера нет способа узнать, достиг ли он своего пункта назначения.

Единственный способ узнать это - заставить клиента отправить ACK обратно. (Кроме того, и клиент, и сервер должны иметь механизмы повторной отправки на случай потери пакетов).

Так что явно что-то еще происходит в вашем коде (или с реализацией .Net udp)

EDIT:

После замечания Николая я проверил документы. И действительно, в .Net существует различие между «подключением» или «отсутствием соединения» при использовании UDP.

Если вы используете такой код:

UdpClient udpClient = new UdpClient(11000); //sourceport
try{
     udpClient.Connect("www.contoso.com", 11000); //'connect' to destmachine and port
     // Sends a message to the host to which you have connected.
     Byte[] sendBytes = Encoding.ASCII.GetBytes("Is anybody there?");
     udpClient.Send(sendBytes, sendBytes.Length);

тогда, по-видимому, вы «связаны»

Однако, если вы используете такой код:

     UdpClient udpClientB = new UdpClient();
     udpClientB.Send(sendBytes, sendBytes.Length, "AlternateHostMachineName", 11000);

затем вы можете отправить кому угодно без «подключения».

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...