Как изящно восстановить из исключения сокета С# udp

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

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

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

Ответ 1

Я думаю, вы правы, говоря: "сервер не должен знать". Если вы отправляете 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);

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

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