SocketException в неправильном потоке - PullRequest
2 голосов
/ 12 января 2012

Я использую класс C # UdpClient для сетей UDP. Существует один UdpClient объект, связанный с фиксированным локальным портом, но не с какой-либо удаленной конечной точкой, поскольку он должен иметь возможность отправлять / получать в / из нескольких разных конечных точек.

У меня есть два потока: один для отправки, один для получения. Теперь, когда я отправляю данные в конечную точку, которая существует, но не прослушивает этот порт, я ожидаю SocketException. И я получаю один. К сожалению, это не мой вызов Send, который возвращает исключение, а вызов Receive. Поэтому в моем потоке отправки я отправляю данные в «недопустимую» конечную точку, и мой поток получения получает исключение. К сожалению, в тот момент я, конечно, понятия не имел, какая конечная точка привела к возникновению этого исключения.

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

К сожалению, SocketException не дает мне конечную точку, вызвавшую ошибку.

Есть идеи? Можно ли как-то сделать исключение в потоке-отправителе?

Помощь очень ценится.

Ответы [ 2 ]

3 голосов
/ 12 января 2012

Когда вы send() пакет UDP, он выходит на провод и фактически исчезает.Вы не должны предполагать, что вообще получите какой-либо отзыв.

Иногда, если в месте назначения нет прослушивателя, назначение может быть достаточно любезным, чтобы отправить обратно сообщение ICMP_UNREACH_PORT,Маршрутизаторы между могут быть достаточно любезны, чтобы доставить это сообщение в вашу операционную систему.Если это произойдет, пройдет много времени после того, как вы вернете исходный вызов send().Для ICMP_UNREACH_PORT ОС обычно кэширует его и сообщает об ошибке в следующий раз, когда вы выполните send() в том же месте назначения.Другие сообщения ICMP (вы не упомянули, какое исключение вы получаете) могут повлиять на другие вызовы.

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

0 голосов
/ 12 января 2012

Я думаю, что это ожидаемое поведение для UDP. UDP send() не является операцией блокировки, поэтому он не будет ожидать потенциальной ошибки. (Не говоря уже о том, что вы не можете полагаться на то, что сообщения об ошибках надежно принимаются при отправке на активный хост с закрытым портом - он может быть защищен брандмауэром, ограничен по скорости или иным образом отброшен из-за перегрузки и т. Д.)

Вы можете connect() сокет UDP для конкретной удаленной конечной точки, который выделит уникальный номер порта и позволит ОС [наиболее вероятно] отличать ошибки от этой конкретной конечной точки от любого другого случайного хоста. Но опять же, вы не должны полагаться на способность обрабатывать эти ошибки.

Жаль, что в этом исключении нет больше информации. Это похоже на недосмотр в том, как .NET обрабатывает сокеты UDP. Согласно документации , вам необходимо проверить ErrorCode исключения и соответствующим образом обработать ошибку . (что в вашем случае может означать игнорирование ошибки.)

...