2009-11-05 2 views
2

Я хотел бы сделать TCP-клиент, который делает несколько соединений, в то время как цикл select(), который принимает данные от них, работает в отдельном потоке. Я не уверен, что это возможно, потому что цикл select() уже запущен и, следовательно, я не вижу, как он «заметит» новый сокет, добавленный, даже если будут рассмотрены проблемы безопасности потоков.Можно выбрать() для клиентов, а не только для серверов?

Есть ли способ сделать это, или я должен создать новый поток и использовать recv() каждый раз, когда я создаю новое соединение?

(под редакцией для ясности.)

ответ

2

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

This page имеет код, показывающий, как это делается.

+0

Хорошо спасибо, поэтому, хотя функция select() работает в цикле, и сокет добавляется из совершенно другого потока, где используется функция connect(), он все равно заметит, что набор для чтения только что получил новое дополнение и будет начать получать данные по нему? Это немного противоречиво, но я попробую. – 2009-11-05 16:03:28

+0

А? Потоки? Я думал, вы сказали «единственная нить» в вопросе. Измените свой вопрос, чтобы более четко описать, как использовать потоки. FD_SET (очень вероятно) не является потокобезопасным, поэтому вам нужно позаботиться о добавлении сокетов в общий набор из многих потоков. – unwind

+0

Извините, я предположил, что это было ясно, потому что select() должен запускаться в цикле, поэтому, если я не сделаю все мои подключения до того, как попасть в цикл, я как бы вынужден сделать свои подключения в отдельном потоке. – 2009-11-05 16:29:05

0

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

  • Установка клиентского сокета не должна блокироваться.
  • Позвоните по телефону(). Вероятно, он вернется с ошибкой EINPROGRESS (соединение выполняется, вы не заблокированы, потому что сокет не блокируется).
  • Теперь выберите() с FD_SET, настроенным для отслеживания клиент-сокета как «готового к записи». Также вы можете установить тайм-аут.
  • Анализ результата select().
  • Проанализируйте, была ли неудача или успешность работы последнего клиента.

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

0

Один простой способ сделать это также select на трубе. После того, как вы упорядочиваете так, чтобы поток также установил select на новое соединение, вы пишете один байт на трубе. Это приводит к тому, что поток выходит из select. Когда он замечает, что труба читается, она считывает байты, чтобы «перезагрузить» трубу, чтобы она снова была готова к использованию, обновляет свои наборы дескрипторов файлов и возвращается к select ing.

Смежные вопросы