Во-первых, это, возможно, зависит от платформы, и вы не упоминаете платформу, на которой вы работаете; тем не менее, 10054 - это WSAECONNRESET
, поэтому я предполагаю платформу Windows какой-то.
Во-вторых, как указывалось ранее, нет связи с UDP. Ваш звонок на Connect()
в клиенте просто приводит к тому, что сетевой код на вашем клиентском компьютере позволяет вам инициировать Send()
вызовы вместо SendTo()
вызовов и просто назначает адрес по умолчанию, на который вы отправляете данные при вводе Send()
звонки по адресу, указанному для звонка на Connect()
.
В-третьих, я удивлен, что вы получаете WSAECONNRESET
, а не ERROR_PORT_UNREACHABLE
; однако основная причина, вероятно, та же. Стек UDP на удаленной машине, скорее всего, отправит ошибку ICMP Port Unreachable, если на порте, на который вы отправляете, нет открытого сокета. Итак, если ваш клиент отправляет данные, а затем закрывает сокет, а затем ваш сервер отправляет данные обратно на адрес клиента, вы получите порт, недоступный, и некоторые версии Windows могут преобразовать это в ошибку сброса соединения ...
Проблема с этими недоступными ошибками порта ICMP заключается в том, что они сообщаются через код Winsock при сбое ожидающего вызова UDP Recv / RecvFrom. Как я объясняю здесь и вопрос здесь стек UDP, очевидно, знает адрес, который сгенерировал порт, недоступный, но он не передает эту информацию вызывающей стороне, поэтому вы ничего не можете сделать сопоставить эти сообщения с чем-то полезным. Возможно, вы работаете в версии Windows, предшествующей Vista, и стек UDP делает что-то полезное с адресом, и он сообщает об ошибке в правильный сокет, но не стоит на это ставить.
Наконец, у вас все равно есть проблема; ошибка недоступности порта ICMP не доставлена надежно, поэтому вы не можете точно знать, что получите ошибку, если попытаетесь отправить данные UDP удаленному клиенту. ИМХО, это означает, что вы не должны полагаться на это, даже если это иногда работает.
Вы, очевидно, пытаетесь создать какой-то протокол, ориентированный на соединение, поверх UDP (почему иначе ваш сервер будет удерживать адреса клиентов). Вам нужно будет сделать гораздо больше, чтобы создать жизнеспособное псевдосоединение по UDP, и одна из первых вещей, которые нужно понять, это то, что единственный способ узнать, когда клиент ушел, - это установить собственный тайм-аут и «отключить» ваш псевдо-соединение, если вы не слышите от них в течение определенного периода времени.
Конечно, это не отвечает на ваш вопрос; как избежать исключения Я ожидаю, что вы не можете. Причиной исключения, вероятно, является код возврата «сбой» из вызова Recv()
или RecvFrom()
, и сетевой код python, вероятно, преобразует все такие возвраты ошибок в исключения для вас.