The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"реализация функции socket recv с таймаутом."
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"реализация функции socket recv с таймаутом."  
Сообщение от ufobject email(ok) on 15-Дек-06, 17:15 
Доброго времени суток вам, народ!
столкнулся тут с проблемой сокетов, а именно с recv. Если я оставляю сокет блокируемым и ожидаю данные, то этот самый recv замораживает процесс пока не получит эти самые данные. Оно конечно и хорошо в некоторых случаях, но в моем случае случается так, что после успешного коннеста, клиент вылетает из сети, а сервер ждет этим самым recv обещенные данные и ясно дело не дожидается. Нашел выход из этой ситуации в установке таймаута на recv и использование select для слежения за сокетом. Ниже привожу исходник функции, которую использую...

int vm_recive_socket (int soc, char rbuf[], int timeout)
{
    long arg;
    int sock,res,valopt;
    struct timeval tv;
    socklen_t lon;
    fd_set myset;
    struct sockaddr_in addr;

    tv.tv_sec = timeout;
    tv.tv_usec=0;

    arg=fcntl(soc,F_GETFL,NULL);
    arg |= O_NONBLOCK;
    fcntl(soc, F_SETFL,arg);

    res = recv(soc, rbuf, sizeof(rbuf), 0);

    FD_ZERO (&myset);
    FD_SET (soc,&myset);

    if (select (soc+1,&myset,NULL,NULL,&tv)==0)
    {
      printf ("timeout\n");
      return -100;
    }
    //?????????? ??????? ????? ??????
    arg = fcntl(soc, F_GETFL, NULL);
    arg&= (~O_NONBLOCK);
    fcntl(soc, F_SETFL, arg);
    return res;
}

С таймаутом у меня все получилось. Если во время соединения клиент не шлет данные, через указанное в timeout время, возвращается -100 и я знаю что произошло.. НО! Вниманияе вопрос Ж)) если приходят данные, функция возвращает отрицательное значение а  strerror(errno) выдает ошибку "ERROR: Resource temporarily unavailable". Проверка переменной rbuf подтверждает то, что данные отсутствуют. Что я упустил? В чем ошибка?
P.S.
И еще.. Чуть не забыл. Объясните мне, пожалуйста, что сие означает? "arg&= (~O_NONBLOCK);"

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

 Оглавление

Сообщения по теме [Сортировка по времени, UBB]


1. "реализация функции socket recv с таймаутом."  
Сообщение от kerdan on 15-Дек-06, 21:01 
Функция recv() может вернуть меньше данных (или не вернуть) в случае обрыва, ошибки, связанной с сокетом, если ты в последнем аргументе укажешь флаг MSG_PEEK.

Почитай ещё маны про сокеты. линуксовые меня, помнится, очень удволетворили исчерпываюей инфой, да еще и с примерами.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

2. "реализация функции socket recv с таймаутом."  
Сообщение от ufobject (ok) on 16-Дек-06, 14:21 
>Функция recv() может вернуть меньше данных (или не вернуть) в случае обрыва,
>ошибки, связанной с сокетом, если ты в последнем аргументе укажешь флаг
>MSG_PEEK.
>
>Почитай ещё маны про сокеты. линуксовые меня, помнится, очень удволетворили исчерпываюей инфой,
>да еще и с примерами.


Меня больше смущает select. Может я с ним что то перемудрил? Маны я уже читал и видимо что то не догнал.. мне бы очень хотелось конкретной поправки, так как я считаю что сделал все правильно, но ведь это не работает Ж)

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

3. "реализация функции socket recv с таймаутом."  
Сообщение от Laphroaig email on 16-Дек-06, 15:32 
Что-то не пойму что эта функция делает:
1. Сначала делаешь сокет неблокируемым (arg |= O_NONBLOCK;)
2. Вызываешь recv, если данные системой от клиента еще не получены, она вернет -1 и errno=EWOULDBLOCK, т.к. этот вызов теперь неблокирующий.
3. Вызываешь select и ждешь когда на дескриптор придут данные (если они придут, когда ты их читать будешь? при следующем вызове?)
4. Делаешь сокет снова блокируемым (  arg&= (~O_NONBLOCK) )
Бред какой-то.

Если во время recv происходит разрыв связи на блокируемых сокетах то он вернет 0. Это и есть сигнал о том что соединения больше нету.

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

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

4. "реализация функции socket recv с таймаутом."  
Сообщение от ufobject (ok) on 17-Дек-06, 13:35 
>Что-то не пойму что эта функция делает:
>1. Сначала делаешь сокет неблокируемым (arg |= O_NONBLOCK;)
>2. Вызываешь recv, если данные системой от клиента еще не получены, она
>вернет -1 и errno=EWOULDBLOCK, т.к. этот вызов теперь неблокирующий.
>3. Вызываешь select и ждешь когда на дескриптор придут данные (если они
>придут, когда ты их читать будешь? при следующем вызове?)
>4. Делаешь сокет снова блокируемым (  arg&= (~O_NONBLOCK) )
>Бред какой-то.
>
>Если во время recv происходит разрыв связи на блокируемых сокетах то он
>вернет 0. Это и есть сигнал о том что соединения больше
>нету.
>
>А если хочешь использовать неблокируемые сокеты, то читай умные книжки, методом тыка
>тут не разберешся, достаточно сложная тема.


Я использую неблокируемые сокеты успешно при accept и при connect. Я не нашел в манах ничего конкретного по recv. Я не могу найти нормального примера работы recv+select. Я сделал так, как посчитал нужным и это не работает. Именно по этому я и пишу в форум. А про то, что recv возвращает 0, то это еще вопрос спаорный, так как у меня случаются ситуации, при которых клиент ЖЕСТКО ресетится и видимо не посылает break серверу, что влечет  за собой повисание сервера на ожидании данных, именно поэтому мне и необходим таймаут. Если есть ссылка на нормальную статью по таймаутам recv'а, был бы рад ей воспользоваться.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

5. "реализация функции socket recv с таймаутом."  
Сообщение от BigHo on 17-Дек-06, 20:05 
Закрытие коннекта лучше отслеживать через четвертый аргумент select, а не установкой timeout.

Теперь по существу. В каких значениях может находится значение timeout ? Потому как если допустимо нулевое значение таймаута, то функция select в некоторых ОС всегда будет возвращать 0, даже если порция данных была успешно получена, чтобы соответствовать poll. Кстати, что за ОС ? Попробуй также воспользоваться вышеумянутым poll(2) вместо select(2).

P.S. по "Чуть не забыл. Объясните мне, пожалуйста, что сие означает".. Вообщем это означает снятие флага "без блокировки системных функций ввода/вывода". Собственно если все операции производятся без блокировки, то его нужно один раз установить и никогда не снимать.

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

P.P.P.S. еще есть AIO вызовы (aio_*, lio_*, если конкретно aio_read(2), aio_write(2). Прямо-таки панацея от этих и других бед). Правда только для connected сокетов.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

6. "реализация функции socket recv с таймаутом."  
Сообщение от ufobject email(ok) on 18-Дек-06, 11:14 
>Закрытие коннекта лучше отслеживать через четвертый аргумент select, а не установкой timeout.
>
>
>Теперь по существу. В каких значениях может находится значение timeout ? Потому
>как если допустимо нулевое значение таймаута, то функция select в некоторых
>ОС всегда будет возвращать 0, даже если порция данных была успешно
>получена, чтобы соответствовать poll. Кстати, что за ОС ? Попробуй также
>воспользоваться вышеумянутым poll(2) вместо select(2).
>
>P.S. по "Чуть не забыл. Объясните мне, пожалуйста, что сие означает".. Вообщем
>это означает снятие флага "без блокировки системных функций ввода/вывода". Собственно если
>все операции производятся без блокировки, то его нужно один раз установить
>и никогда не снимать.
>
>P.P.S. согласен с Laphroaig, что подобный стиль описания сокетов немного коряв. Желательно
>обработать все ошибки, которые могут проявиться при вызове системных вызовов, и
>не совмещать передачу с прослушиванием таким способом. Т.е. обычно люди сперва
>убеждаются, ушли ли данные, а только потом пытаются получить ответ.
>
>P.P.P.S. еще есть AIO вызовы (aio_*, lio_*, если конкретно aio_read(2), aio_write(2). Прямо-таки
>панацея от этих и других бед). Правда только для connected сокетов.
>

Благодарствую BigHo :)
1)timeout не может быть нулем, предпологаю что будет 1-5 секунд.. Где-то так.
2) ОС Linux. 2.6.16, дистриб Gentoo, но программа будет переносится на урезанный Suse.
3) Connected сокет? Что это? Это сокет полсле успешного connect'а :)? Или это еще какой-то тип сокета? Не понял. :(
4) Я понимаю что происходит в этих двух строках:
    arg |= O_NONBLOCK;
    arg&= (~O_NONBLOCK);
Я не совсем понимаю логических действий "|=", "&=", "~". Можно в двух словах?

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

7. "реализация функции socket recv с таймаутом."  
Сообщение от BigHo on 18-Дек-06, 12:24 

>Благодарствую BigHo :)
>1)timeout не может быть нулем, предпологаю что будет 1-5 секунд.. Где-то так.
>
>2) ОС Linux. 2.6.16, дистриб Gentoo, но программа будет переносится на урезанный
>Suse.

Тогда все в предыдущем посте - применимо для этих систем.

>3) Connected сокет? Что это? Это сокет полсле успешного connect'а :)? Или
>это еще какой-то тип сокета? Не понял. :(

Типа того. Можно еще сказать - сокет, которому достаточно send вызова и необязательно использование sendto или sendmsg. У этих вызовов есть аргумент, наподобие того, что указывается при инициализации соединения вызовом connect.

>4) Я понимаю что происходит в этих двух строках:
>    arg |= O_NONBLOCK;
>    arg&= (~O_NONBLOCK);
>Я не совсем понимаю логических действий "|=", "&=", "~". Можно в двух
>словах?

Это можно посмотреть в любом учебнике по C/C++, битовые операции. Это НЕ ЯВЛЯЕТСЯ ЛОГИЧЕСКИМИ операциями. Т.е. любая битовая операция действует над группой бит (регистром или ячейкой памяти). Логическими операциями являются: "&&", "||", "!". Если переносить эти операции в операции над группами бит, то им можно соответственно сопоставить: "&", "|", "~". В этом случае каждый отдельный бит можно рассматривать как отдельное булево значение.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

8. "реализация функции socket recv с таймаутом."  
Сообщение от ufobject email(ok) on 18-Дек-06, 14:00 
>
>>Благодарствую BigHo :)
>>1)timeout не может быть нулем, предпологаю что будет 1-5 секунд.. Где-то так.
>>
>>2) ОС Linux. 2.6.16, дистриб Gentoo, но программа будет переносится на урезанный
>>Suse.
>
>Тогда все в предыдущем посте - применимо для этих систем.
>
>>3) Connected сокет? Что это? Это сокет полсле успешного connect'а :)? Или
>>это еще какой-то тип сокета? Не понял. :(
>
>Типа того. Можно еще сказать - сокет, которому достаточно send вызова и
>необязательно использование sendto или sendmsg. У этих вызовов есть аргумент, наподобие
>того, что указывается при инициализации соединения вызовом connect.
>
>>4) Я понимаю что происходит в этих двух строках:
>>    arg |= O_NONBLOCK;
>>    arg&= (~O_NONBLOCK);
>>Я не совсем понимаю логических действий "|=", "&=", "~". Можно в двух
>>словах?
>
>Это можно посмотреть в любом учебнике по C/C++, битовые операции. Это НЕ
>ЯВЛЯЕТСЯ ЛОГИЧЕСКИМИ операциями. Т.е. любая битовая операция действует над группой бит
>(регистром или ячейкой памяти). Логическими операциями являются: "&&", "||", "!". Если
>переносить эти операции в операции над группами бит, то им можно
>соответственно сопоставить: "&", "|", "~". В этом случае каждый отдельный бит
>можно рассматривать как отдельное булево значение.

Я попробовал воспользоваться aio_read, вроде все по ману, но ошибка при компиляции:
/tmp/cccrhHxm.o: In function `vm_recive_socket(int, char*, int)':
/home/vmctrl/extlib.cpp:328: undefined reference to `aio_read'
collect2: ld returned 1 exit status

ктмпилю следующей строкой:
g++ -I/usr/include/mysql -I/usr/include/mysql++ server.cpp -o mserver -g -O0 -lmysqlclient -lm

    include <aio.h>
........
    struct aiocb *aiocbp;
    aiocbp->aio_fildes=sock;
    aiocbp->aio_buf=rbuf;
    aiocbp->aio_nbytes=1;
    res = aio_read(aiocbp);
........

такая ошибка раньше вылетала у меня когда я пытался скомпилить исходник c++ с посощью "cc"...

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

9. "реализация функции socket recv с таймаутом."  
Сообщение от BigHo on 18-Дек-06, 15:54 
>такая ошибка раньше вылетала у меня когда я пытался скомпилить исходник c++
>с посощью "cc"...

Попробуй использовать линковку с библиотекой rt (LDFLAGS += -lrt)

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру