Как восстановиться корректно с исключительной ситуации сокета C# udp

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

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

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

10
задан Gearoid Murphy 10 April 2010 в 12:25
поделиться

1 ответ

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

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

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

РЕДАКТИРОВАТЬ:

После замечания Николая я проверил документацию. И действительно, в .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);

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

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

1
ответ дан 4 December 2019 в 04:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: