Как выяснить причину сообщения Socket.Select () об ошибке - PullRequest
3 голосов
/ 16 февраля 2009

Я звоню Bind(), а затем Listen() на System.Net.Sockets.Socket. Ни один из этих вызовов не выдает исключение.

Позже я звоню:

Socket.Select(myreadlist,mywritelist,myerrorlist,0);

с myreadlist и myerrorlist, содержащим данный сокет. Выберите сообщает, что в моем сокете произошла ошибка, оставив сокет в errorList, вместо удаления его из списка. Нигде в программе Выдается исключение SocketException.

Кажется, я не могу понять, как правильно задавать вопрос системе: «Хорошо, так что пошло не так?»

Кто-нибудь знает?

Спасибо, Лукас

edit: добавить 4-й аргумент = 0 для select + лучше объяснил, как select () сообщает мне, что произошла ошибка.

Ответы [ 2 ]

1 голос
/ 16 февраля 2009

Я не знаю C #, но я знаю сокеты UNIX. Моей первой мыслью было то, что вы не вызывали accept () для сокета до выбора для чтения, но (и это доказательство того, что я знаю о сокетах меньше, чем я думал), вы можете выбрать в состоянии прослушивания, чтобы увидеть, какие сокеты могут быть приняты. Ну что ж, мы живем и учимся даже в преклонном возрасте: -)

Во всяком случае, ссылаясь на документы MSDN здесь , найденные через Google с помощью ("c #" socket bind listen select), он гласит:

If you receive a SocketException, use SocketException.ErrorCode to obtain the specific error code. Once you have obtained this code, you can refer to the Windows Socket Version 2 API error code documentation in MSDN for a detailed description of the error.

Похоже, что эти коды ошибок задокументированы здесь , найденные с помощью поиска Google (документация по кодам ошибок Windows Socket Version 2 API в MSDN).

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

Одна вещь, которая кажется неуместной: у прототипа вызова есть четвертый аргумент, число микросекунд, которые нужно ждать, если не будет активности. Ваш код в вопросе не имеет этого. Теперь, как я уже сказал, я мало знаю о C #, так что он может что-то по умолчанию (или, может быть, вы просто оставили это вопрос случайно).

Но я бы проследил за известной ошибкой, если вы используете -1 (или она по умолчанию равна -1): подробности см. здесь , но в основном это означает, что -1 возвращается немедленно, а не ждет вечно. Обходной путь - использовать -2, чтобы дать вам час или около того, но вам все равно придется учитывать тот факт, что он может вернуться, даже если не было никакой активности.

Если это не , выдающее исключение, а просто устанавливающее индикацию ошибки в myerrorlist, это проблема хейера. Я не вижу ничего, кроме документов, показывающих, как это легко понять, но я бы посмотрел на эти возможности.

  • Вы можете вызывать функции WSA (например, WSAGetLastError()), чтобы понять это. Я не уверен, насколько легко это из C #. Вы можете попробовать accept() ошибочный сокет и посмотреть, дает ли это исключение, подробно описав причину проблемы.
  • Класс Socket имеет член Handle, который является дескриптором операционной системы для сокета. После этого можно извлечь информацию об ошибке.
  • Задумывались ли вы о том, чтобы использовать потоки для обработки соединений и вообще обойти использование select() (т.е. использовать только accept(), но из нескольких потоков)?

Еще одна вещь, которую я обнаружил, связана с отладкой сокетов. Эта страница имеет раздел внизу, который показывает, как выполнять трассировку сети. .NET 2, очевидно, не поддерживал это для select(), но это могло измениться в последней версии.

0 голосов
/ 16 февраля 2009

Документация для вызова Select () гласит:

Если вы сделали неблокирующий вызов Connect, параметр checkerror определяет сокеты, которые не были успешно подключены.

И документация для метода Poll () (который предлагается использовать для определения состояния отдельного сокета) в режиме SelectError гласит:

true, если при обработке соединения, которое не блокируется, и соединение не удалось; -или же- Значение true, если OutOfBandInline не установлен и доступны внеполосные данные; в противном случае возвращает false.

Исходя из этого, я бы сказал, что это единственные два условия, при которых сокет указывает на состояние ошибки, не вызвав ранее исключения. Вы не упомянули, что вызывали Connect (), но если вы это сделаете, я бы проверил, действительно ли он устанавливает соединение. Внеполосные данные довольно редки, но, возможно, ваш другой конечный сокет делает что-то странное.

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