Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > select()


Автор: Pete 7.7.2006, 16:59
Правильно ли я понимаю, как она работает?
Здесь c_sock и extsd -- 2 сокета (TCP). Я их отслеживаю на предмет появления новых символов. Если в какой-то сокет что-то приходит, перенаправляю это в другой и наоборот (см. resend()). Если какой-то сокет закрыт, то, насколько я понял, select() вывалится и это событие отловится изменением соответствующего дескриптора в 3-ем наборе (efds).
В maxfd хранится максимальный из файловых дескрипторов из набора (наборы одинаковы: c_sock и extsd).

Код
FD_ZERO( &rfds );
FD_ZERO( &efds );
FD_SET( c_sock, &rfds );
FD_SET( c_sock, &efds );
maxfd = c_sock;
/* ..... */
FD_SET( extsd, &rfds );
FD_SET( extsd, &efds );
maxfd = (extsd > maxfd ? extsd : maxfd);


Это код, в правильности которого я сомневаюсь:

Код
if (select( maxfd + 1, &rfds, NULL, &efds, NULL ) < 0 ) {
  printf( "ERROR: %s:%d: %s\n", __FILE__, __LINE__, strerror( errno ) );
  exit( EXIT_FAILURE );
} else {
  
  if        (FD_ISSET( c_sock, &efds )) {
    close( extsd );
    puts( "> Connection closed." );
    exit( EXIT_SUCCESS );
  } else if (FD_ISSET( extsd,  &efds )) {
    puts( "Remote server disconnected." );
  }
  
  if        (FD_ISSET( extsd,  &rfds )) {
    n = resend( extsd, c_sock );
    printf( "> %d bytes was sent by server\n", n );
  } else if (FD_ISSET( c_sock, &rfds )) {
    n = resend( c_sock, extsd );
    printf( "> %d bytes was sent by client\n", n );
  } else
    printf( "ERROR: %s:%d: %s\n", __FILE__, __LINE__, strerror( errno ) );
  
}


А вот и resend():

Код
int
resend( int from, int to )
{
  int  n;
  int  s = 0;
  char buf[MAX_BUF_LEN];
  
  while ((n = read( from, buf, MAX_BUF_LEN )) > 0)
    {
      write( to, buf, n );
      s += n;
      if (n < MAX_BUF_LEN) break;
    }
  
  return s;
}
 

Автор: bsa 7.7.2006, 22:25
И в чем проблема?
На первый взгляд должно работать. Я использовал select. Ничего непредсказуемого не заметил. 

Автор: Pete 8.7.2006, 00:59
Должно-то оно должно, только не работает. Проблема в том, что когда клиент пишет что-то в сокет (send'ом), сервак должен это прочитать и ответить (recv'ом). Фактически, вышеизложенный код --- часть проги-посредника между клиентом и сервером (реализую SOCKS).

Клиент передет нормально, сервак принимает нормально, но когда последний хочет ответить, то посредник виснет на select'е.

Потом мне объяснили, что если указать сокет в 3-ем наборе дескрипторов, то при его закрытии select вываливается, а FD_ISSET от него становится истинным. Это тоже у меня не получилось подтвердить.

В общем, где-то скрыто глобальное непонимание, что очень мешает заставить прогу работать... 

Автор: GrayCardinal 8.7.2006, 05:52
select вроде вываливается не по ошибке если данных нет, а по чтению EOF. Т.е. read должен ноль выдавать, а у вас resend такое не обрабатывает...

Добавлено @ 06:03 
Цитата
... a file descriptor is also ready on end-of-file ...

smile
 

Автор: Pete 9.7.2006, 21:09
Проблемы с read я уже решил. Меня больше интересует вопрос, почему сервак в ответ клиенту на своем конце что-то пихает, а socks-сервер ждет как ни в чем не бывало...

Добавлено @ 21:10 
...вместо того, чтобы переслать это клиенту. 

Автор: bsa 9.7.2006, 21:26
А ты уверен, что socks ждет именно данные от сервера? 

Автор: Pete 9.7.2006, 22:29
Как мне объяснили, он ждет данные и от сервера, и от клиента.

Что только я не пробовал, никакого продвижения. Посылаю в сервере сообщение клиенту, а socks-сервак встает на select. Даже не знаю, что делать. 

Автор: Pete 10.7.2006, 20:39
Все, разобрался. Дело было в том, что я не востанавливал fd_set'ы после каждого выхода из select()smile 
Говорил же: банальная ошибка, а сколько времени ушло на ее поиск! smile 
Можно закрывать) smile  

Автор: GrayCardinal 11.7.2006, 00:00
Цитата
Говорил же: банальная ошибка

В следующий раз сразу строчку говорите, где собственно банальная ошибка smile  smile  smile  smile  

Автор: Pete 11.7.2006, 00:31
Дело не в строчке, а в понимании (точнее, непонимании) работы функции. 

Если кому интересно, надо было добавить во втором блоке кода, сразу перед выходом из if (строка 22), это:

Код

FD_ZERO( &rfds );
FD_ZERO( &efds );

FD_SET( c_sock, &rfds );
FD_SET( extsd,  &rfds );
FD_SET( c_sock, &efds );
FD_SET( extsd,  &efds );


Добавлено @ 00:32 
Спасибо за помощь! 

Автор: Einstein 16.7.2006, 17:05
Добрый день, подскажите хто сможет, я приехал с Канады и мне нужен совет по поводу компании где можно устроится в Киеве. Я программист С++. Заранее благодарен 

Автор: GrayCardinal 16.7.2006, 19:13
Цитата

Добрый день, подскажите хто сможет, я приехал с Канады и мне нужен совет по поводу компании где можно устроится в Киеве. Я программист С++. Заранее благодарен

А ты приколист. smile smile smile
А что в Киев ? Дуй в Сибирь. Медведей правда не обещаю smile Да и чтоб устроится надо 100т строк самопалки. У вас их есть ? 

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