Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > C/C++ Сетевое программирование
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.10.2009, 18:26   #1
JohnnyQ
 
Регистрация: 13.10.2008
Сообщений: 6
По умолчанию ждать полный таймаут в select()

Добрый день! Есть небольшой вопрос по программе под Linux.

Код:
struct timeval tv;    // устанавливаем время ожидания в 1 сек.
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    fd_set rfds;        // проверяем наличие данных в сокете, установив файловый дескриптор сокета в множестве "на чтение"
    FD_ZERO(&rfds);    // очищаем множество "на чтение"
    FD_SET(my_socket, &rfds);    // помещаем дескриптор сокета в множество "на чтение"
        
    int i = select(my_socket+1, &rfds, NULL, NULL, &tv);    // контроллируем активность сокета
//-----------------зафиксировано наличие данных в сокете--------------------    
    
    if (i > 0)    // т.е. таймаут не успел завершиться
    {
//----------------------извлекаем данные из сокета---------------------------
 
            if (recvfrom(my_socket, arp_packet_r->buf, arp_packet_r->size, 0, NULL, NULL) < 0)
        {
            perror("Error at recv()\n");
             exit(1);
        }
//---------------------------анализируем ответ------------------------------    
        int result = memcmp (arp_req.target_ip, arp_rep.sender_ip, IP_LENGTH );    // проверяем, что ответ пришел от того хоста,
                                        // который запрашиваем
        if(    arp_rep.type == arp_req.type ||        //сравниваем 
            arp_rep.operation == htons(OTV)        //параметры            
            || result == 0    )                                                            
        {
            printf("Its busy. \n");
            return 0;
        }
    }
//  продолжение программы   . . .
В этой программе ждем данные в сокете 1 секунду и если ничего не приходит, то идем дальше. Но если в процессе ожидания ответа придёт хоть один не наш пакет, то программа примет его за ответ и не дождется завершения таймаута, хотя возможно нужный нам пакет еще придет.
Отсюда вопрос: как можно организовать ожидание завершения полного таймаута?
JohnnyQ вне форума Ответить с цитированием
Старый 10.10.2009, 19:49   #2
BaronTreep
Форумчанин
 
Регистрация: 29.05.2009
Сообщений: 320
По умолчанию

Если следовать манам:

http://www.opennet.ru/man.shtml?topi...ry=2&russian=0
http://www.opennet.ru/cgi-bin/openne...tut&category=2
http://www.opennet.ru/man.shtml?topi...ry=3&russian=0

можно придумать решение, но оно не хорошее - непереносимо, т.е. только для Linux. А именно - после того как функция select вернет управление tv.tv_sec будет содержать количество прошедших секунд, а tv.tv_usec - микросекунд, поэтому можно оставшееся время банально "дождать" с помощью usleep:

Код:
const TIMEOUT = 5000000;
//...
    int i = select(my_socket+1, &rfds, NULL, NULL, &tv);
    if (tv.tv_sec*1000000 + tv.tv_usec < TIMEOUT) {
        usleep(TIMEOUT - tv.tv_sec*1000000 + tv.tv_usec);
    }
Кстати коментарии неправильные, например:
Цитата:
Сообщение от man
При успешном завершении select и pselect возвращают количество описателей, находящихся в наборах, причем это количество может быть равным нулю, если время ожидания на исходе, а интересующие нас события так и не произошли.
BaronTreep вне форума Ответить с цитированием
Старый 11.10.2009, 14:56   #3
JohnnyQ
 
Регистрация: 13.10.2008
Сообщений: 6
По умолчанию

но мне же нужно не дождать время, а выбирать из приходящих на сокет ответов нужный мне.

наверно лучше организовать цикл while?
например:
Код:
while(  tv.tv_sec != 1)
{
  int i = select(my_socket+1, &rfds, NULL, NULL, &tv);
....

}

Последний раз редактировалось JohnnyQ; 11.10.2009 в 15:05.
JohnnyQ вне форума Ответить с цитированием
Старый 11.10.2009, 23:59   #4
BaronTreep
Форумчанин
 
Регистрация: 29.05.2009
Сообщений: 320
По умолчанию

Тогда нужно накапливать время в цикле. Допустим в TIMEOUT общее количество мили-секунд, T - текущая часть мили-секунд:

Код:
int TIMEOUT = 1000000;
int T = 0;
int rec;

// тут описание структуры tv и макросы

while( T < TIMEOUT ) {
    tv.tv_sec = (TIMEOUT - T) / 1000000;
    tv.tv_usec = (TIMEOUT - T) % 1000000;
    rec = select(my_socket+1, &rfds, NULL, NULL, &tv);
    T += tv.tv_sec * 1000000 + tv.tv_usec;
    //...
}
//...
Так лучше?

Последний раз редактировалось BaronTreep; 12.10.2009 в 00:13.
BaronTreep вне форума Ответить с цитированием
Старый 12.10.2009, 12:08   #5
JohnnyQ
 
Регистрация: 13.10.2008
Сообщений: 6
По умолчанию

ну почти)))
tv.tv_usec и tv.tv_sec возвращают количество не пройденных секунд, а оставшихся... поэтому я сделал вот так:
Код:
int TIMEOUT = 1000000;
while( TIMEOUT!=0 ) {
 tv.tv_sec = TIMEOUT  / 1000000;
 tv.tv_usec = TIMEOUT % 1000000;
rec = select(my_socket+1, &rfds, NULL, NULL, &tv);
...
  TIMEOUT= tv.tv_sec * 1000000 + tv.tv_usec;
}
вроде работает...

Последний раз редактировалось JohnnyQ; 12.10.2009 в 12:11.
JohnnyQ вне форума Ответить с цитированием
Старый 12.10.2009, 22:16   #6
BaronTreep
Форумчанин
 
Регистрация: 29.05.2009
Сообщений: 320
По умолчанию

Удивительно!
BaronTreep вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
В зависимости от выбора в Select изменить значения другого Select Tayfun HTML и CSS 3 18.08.2011 00:05
Select t1.N,t1.FIO,(select t2.acc from t2 where t2.type=1) from t1,t2 mavlon_m SQL, базы данных 2 17.09.2009 15:28
Таймаут и бесконечный цикл Terikon Работа с сетью в Delphi 4 30.03.2009 14:48
Ждать завершения чужого процесса ERASERROR Win Api 2 04.02.2008 08:23
Передача значения в <select></select> kkkggg Gamedev - cоздание игр: Unity, OpenGL, DirectX 1 06.09.2007 00:26