Выход из блокировки потока по TCP, читаемому в C # - PullRequest
2 голосов
/ 25 августа 2009

Мой сервер / клиент начал новый поток "readerThread ()" для чтения входящего трафика TCP. Этот поток блокирует чтение (). Как я могу выйти из этого readerThread ().

Один из способов - запустить другой поток, который закрывает сокет при выходе из потока, так что чтение завершается. Есть ли более чистый / лучший способ сделать это.

Ответы [ 5 ]

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

Я неправильно понял вопрос. Вот что, я думаю, тебе следует сделать.

  • Если вы создали сокет в родительском потоке и используете новый поток только для чтения входящих данных, я бы предложил вызвать Socket.Shutdown (). Таким образом, методы получения будут возвращаться 0 (байты не читаются), и вы можете выйти из метода потока. Завершение работы отключит отправку / получение, но если в буфере есть какие-либо данные, ожидающие отправки / получения, они будут гарантировать, что они отправлены / получены до закрытия сокета. Ваш метод Receive вернет 0, если вы вызовите shutdown, когда сокет заблокирован при получении, но он выдаст исключение сокета с кодом ошибки Socket = Shutdown (или 10058). Так что будьте готовы поймать и справиться с этим.

  • Если вы создаете сокет в новом потоке, и он принимает новые соединения (Socket.Listen () и Socket.Accept) , вы можете соединиться с этим сокетом из родительского потока и отправить 0 байт. Вы можете выйти из нового потока, когда методы получения возвращают 0 байтов.

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

1 голос
/ 25 августа 2009

Я бы использовал связь Asnyncronous Socket. Я написал статью, которая демонстрирует это в моем блоге. Вы можете прочитать здесь:

http://www.andrewrea.co.uk/blog/2009/06/09/Part1SocketProgrammingWithCJAVACAndActionScript30EstablishingABaseConnectionAndCommunicationWithCServerAndAS3.aspx

Andrew

1 голос
/ 25 августа 2009

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

Как правило, однако, я бы использовал вызов select (), который истекает через 1 секунду или около того, чтобы проверить, есть ли данные для чтения, и каждый цикл тайм-аута проверяет, был ли установлен флаг состояния выключения другим потоком.

Но если вы используете чистую блокировку, используйте поток управления, как вы предлагаете.

0 голосов
/ 25 августа 2009

Я несколько озадачен тем, что именно вы делаете: в .NET нет метода read () для класса Socket.

Моя рекомендация - создать второй сокет, который прослушивает определенный порт, и вместо этого иметь блок потоков в Socket.Select . Подключение к этому второму сокету следует рассматривать как запрос на отключение (возможно, после надлежащей аутентификации, например, путем отправки пароля приложения через этот сокет).

0 голосов
/ 25 августа 2009

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

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

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