Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Селект возвращеает сокет когда ничего не пришло 
:(
    Опции темы
Enelar
Дата 11.8.2010, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 141
Регистрация: 13.1.2008

Репутация: нет
Всего: 1



У меня в цикле крутится такой код

Код

  db.SetDebugStr("Enter accept loop");
  fd_set fd; // struct to check
  struct timeval t; // timeout to check

  FD_SET(Connect, &fd); // set connect to struct
 
  struct sockaddr addr; // client addr
  int size; // sizeof addr
  int count = 0; // count per iteration

  t.tv_sec = 0;
  t.tv_usec = 100;

  int sr;
  while ((sr = select(Connect + 1, &fd, NULL, NULL, &t)) > 0)
  {
    printf("accept Select not null\n");
    count++;
    if (count > 30)
      break;
    size = sizeof(addr);
    char ttt[1000];
    sprintf(ttt, "Select return %i", sr);
    db.SetDebugStr(ttt);
    SOCKET s = accept(Connect, &addr, (socklen_t*)&size);
    db.SetDebugStr("accept");

    ... // обработка
  }

Дак вот все работает замечательно, потом бац, селект возвращает 1 а новое соединение не пришло. Ну прога естественно виснет на аксепте.

P.S Connect это сокет который успешно bind и listen прошел.
SetDebugStr это моя функция которая в отличие от принтефа не юзает кеши (напрямую mysql команду).
Приложение однопоточно.

Это сообщение отредактировал(а) Enelar - 11.8.2010, 18:13
PM MAIL   Вверх
Олег2005
Дата 11.8.2010, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

Репутация: 6
Всего: 11



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

PM MAIL WWW MSN   Вверх
Enelar
Дата 12.8.2010, 08:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 141
Регистрация: 13.1.2008

Репутация: нет
Всего: 1



ОС Ubuntu 10.04 LTS

Замечу также что ранее этой ошибки не замечал. И до сих пор не замечаю(если дебажить с ноута или с локалхоста). Но дебажит человек из соседнего района и сервер виснет.

P.S виснет при приходе похожих пакетов обозначающих одно действие но с разными параметрами. Возможна запись мимо памяти, но вроде все проверил...

Встает вопрос, что за макро команды такие?
у меня код следующий
Код

  Connect = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (Connect < 1)
  {
    printf("Cant create socket\n");
    Correct = 0;
  }
  struct sockaddr_in addr;

  int size = sizeof(addr);

  ServerPort = port;
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = INADDR_ANY;
  addr.sin_port = htons(port);
  if (bind(Connect, (struct sockaddr *)&addr, size) < 0)
  {
    printf("Cant bind socket!\n");
    Correct = 0;      
  }

  if (listen(Connect, SOMAXCONN))
  {
    printf("Cant start listen!\n");
    Correct = 0;
  }

  if (!Correct)
     HardShutdown();

PM MAIL   Вверх
ilyagoo
Дата 12.8.2010, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 30
Регистрация: 2.5.2010
Где: Санкт-Петербург

Репутация: нет
Всего: нет



макрокоманды в данном случае:
Код

FD_ZERO
FD_SET
FD_ISSET
FD_CLR

перед каждым вызовом select все три fd_set (в вашем случае только один - на чтение) нужно инициализировать заново.
Код

FD_ZERO( &fd );
FD_SET( Connect, &fd );

и проверять установлен ли бит FD_ISSET сокета после select.

например, рассмотрим ваш код:
1) fd вы не обнулили, а что там находилось? допустим, были ненулевыми какие-то из первых трех битов - это stdin, stdout, stderr (не помню последовательнось).
скажем stdin вдруг стал готов на чтение - select вернул как минимум 1.
2) вы попали в тело цикла и не проверяя, установлен ли ваш Connect после select`а счастливо, виснете в accept, т.к. в этот момент был готов на чтение совершенно другой дескриптор))

все.
PM MAIL   Вверх
Enelar
Дата 12.8.2010, 10:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 141
Регистрация: 13.1.2008

Репутация: нет
Всего: 1



хм.
1) сделаем на всякий случай, но если не ошибаюсь fd_set по умолчанию пустой?
2) если первое не верно, то замечание логично. в противном случае лишняя инструкция.

Добавлено через 2 минуты и 6 секунд
За решение спасибо, наверняка оно верное...
Просто у меня время не ждет, пришлось быстро искать решения.
Сделал сокет неблокирующим.
А то смысл селект ради одного сокета дергать.
PM MAIL   Вверх
ilyagoo
Дата 12.8.2010, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 30
Регистрация: 2.5.2010
Где: Санкт-Петербург

Репутация: нет
Всего: нет



если я не ошибаюсь, неглобальные переменные не инициализируются сами по себе. если сокет был блокирующим, то можно было поместить его в нить.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0731 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.