Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > принудительный выход из select без таймаута


Автор: hash_2000 3.2.2011, 08:55
здравствуйте !
подскажите пожалуйста ктонибудь, как можно сделать принудительный выход из select'а без установленного таймаута, если ни на один из сокетов не пришли данные ...
вот например 

Код



fd_set all_rfd;



// например этот код выполняется в одном потоке 
  while( 1 )
  {
    // заполняем сокетами 
      fd_set rfd;
      memcpy( &rfd, &all_rfd, sizeof( fd_set ) );
      int ret = select( 0, &rfd, 0,0,0 );
     
      ... какойто код
      
  }

// а в другом потоке создаем сокет коннектимся им и добавляем в all_rfd;



.. и для того чтобы на этот сокет ожидались данные нужно чтобы select вернул управление, перезаполнил rfd и передал его снова в select
пример немного притянут за уши, но примерно описывает ситуацию ... 
если ктонибудь знает как можно выкрутиться из такой ситуации ? 
причем охота разобраться именно с функциями winsock без использования всяческих специалезированных библиотек .. заранее благодарен !

Автор: Олег2005 3.2.2011, 18:54
Вы же поставили таймаут равно 0 - значит функция моментально опросит все наборы сокетов - и вернет управление.
Быстрее - никак не получится.....
Прервать работу блокирующей функции - если у вас будет сокет с таймаутом - можно наверное только с помощью WSACancelBlockingCall - это старая функция и ею сейчас уже не пользуются - так как работают на асинхронных сокетах...

Автор: hash_2000 4.2.2011, 06:44
если в select в последнем параметре (TIMEVAL*) передать NULL то функция будет вечно ожидать пока с одним из сокетов в массиве чтонибудь не случится ..
а вот WSACancelBlockingCall проверю .. спасибо за наводку  smile 

Автор: Олег2005 4.2.2011, 11:16
Нужно не NULL - а обычный 0........
Это две большие разницы.....

Автор: Artemon 4.2.2011, 14:45
Цитата(Олег2005 @  4.2.2011,  11:16 Найти цитируемый пост)
Нужно не NULL - а обычный 0........Это две большие разницы.....


#define NULL    0

Автор: Alca 4.2.2011, 15:11
Цитата

Нужно не NULL - а обычный 0........Это две большие разницы.....

Код

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

для указателей как бы используют NULL

Автор: Олег2005 5.2.2011, 19:46
The parameter time-out controls how long the select can take to complete. If time-out is a null pointer, select will block indefinitely until at least one descriptor meets the specified criteria. Otherwise, time-out points to a TIMEVAL structure that specifies the maximum time that select should wait before returning. When select returns, the contents of the TIMEVAL structure are not altered. If TIMEVAL is initialized to {0, 0}, select will return immediately; this is used to poll the state of the selected sockets. If select returns immediately, then the select call is considered nonblocking and the standard assumptions for nonblocking calls apply. For example, the blocking hook will not be called, and Windows Sockets will not yield.

Так что написав простой 0 - получаем моментальное срабатывание.

Автор: hash_2000 7.2.2011, 06:42
кстати вот что нашел в мсдн 
The WSACancelBlockingCall function has been removed in compliance with the Windows Sockets 2 specification, revision 2.2.0.
тоесть она не работает с версией 2 сокетов ... 
я чтото не совсем понимаю, так что получается, во второй версии вообще никак не выйти из блокирующей функции , только что закрыв сокет а мне это какраз таки и не нужно !!!

Автор: Олег2005 7.2.2011, 08:38
Цитата(hash_2000 @  7.2.2011,  05:42 Найти цитируемый пост)
во второй версии вообще никак не выйти из блокирующей функции , только что закрыв сокет а мне это как раз таки и не нужно !!! 

Исполнение функции select  не связано с сокетом вообще - разве что только тем, что она исполняется для существующего сокета.
Как я уже говорил - в современных приложениях блокирующие сокеты уже не применяются как правило, а применяются асинхронные сокеты.
Вообще проблема с прекращением работы блокирующей функции как правило решается иным способом - ее помещают в отдельный поток, а затем при необходимости этот поток убивают извне.
Вспомните - приложение подвисло.......ну и как с ним быть? Его убивают - увы данные все тоже..... 

Автор: hash_2000 7.2.2011, 10:04
если select не связано никак с сокетами то каким тогда способом узнать что в буфер чтения данные пришли ?
или вы предлагаете для каждого пользователя создавать отдельный поток , лично мне кажется что это теже не правильно, ведь если приложение будет работать одновременно например с тысячей пользователей, то буде тысяча простаивающих потоков, ну или не простаивающих, или какието из них будут висеть просто в системе а какието нет , все зависит от программы... но всетаки.. 
а асинхронные сокеты - это имеется ввиду неблокирующие (тогда функция select нужна всеравно ) ?

Автор: Олег2005 8.2.2011, 13:32
Цитата(hash_2000 @  7.2.2011,  09:04 Найти цитируемый пост)
если select не связано никак с сокетами то каким тогда способом узнать что в буфер чтения данные пришли ?

Я не говорил, что select() никак не связан с сокетами.
Эта функция вообще предназначена для отслеживания событий ввода/вывода - например нажатие клавиши на консоли можно тоже отслеживать с ее помощью.
Я говорил так "ИСПОЛНЕНИЕ функции не связано с сокетами"
Сокеты - сами по себе - а функция - сама по себе.
И с сокетами работают вообще без селекта очень часто.
Просто функция очень помогает в отслеживании событий на уже открытых и работающих сокетах.

Цитата(hash_2000 @  7.2.2011,  09:04 Найти цитируемый пост)
или вы предлагаете для каждого пользователя создавать отдельный поток 

Очень часто так и поступают - т.е. на каждого клиента-пользователя - свой поток обработки.
Туда тоже в этот поток можно вставить селект - но этого обычно нет смысла делать.....поток должен будет висеть в памяти и работать сколько надо для полного обслуживания клиента - потому как неизвестно, сколько клиент будет висеть на связи.
На самом деле - модель - 1 клиент- 1 поток - неважная модель именно по той причине как вы отметили - очень много ресурсов надо.
Поэтому для Windows самая популярная модель cетевого I/O  на сервере - это IO Completion Port.
Цитата(hash_2000 @  7.2.2011,  09:04 Найти цитируемый пост)
а асинхронные сокеты - это имеется ввиду неблокирующие (тогда функция select нужна всеравно ) ? 


select() - это типичная функция Unix, и виндовс только поддерживает ее - причем не в полном объеме (первый параметр игнорируется). В Виндовсе есть свои приемы асинхронной работы - WSAAsyncSelect() или более эффективная для консольного исполнения WSA EventSelect() - и никакого селекта там не надо.....или тот же самый порт завершения.....

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)