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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Логика работы таймаута recv, Не понятен принцип работы recv 
:(
    Опции темы
Alexander06
Дата 18.5.2008, 21:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Здравствуйте.

Использую функцию recv для получения данных по TCP
установил таймаут 2 сек на прием данных.
Отправляющая сторона шлет пакеты фиксированной длинны с частотой 100 Гц
Функции recv указываю получить число байт, соответствующее размеру пакета.
В возвращаемом значении согласно описанию - число принятых байт.
Почему-то иногда функция recv считывает меньшее число байт, дочитывая оставшуюся часть пакета за следующий вызов.

Не могу понять..если данные приходят неравномерно, то должен же таймаут заставлять ее ожидать прихода оставшейся части? Тем более что он значительно больше предполагаемых задержек. И почему в следующий заход recv читает именно оставшуюся часть пакета, даже если указать ему считать полную длину?

Зараннее спасибо.
PM MAIL   Вверх
ptr
Дата 19.5.2008, 05:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Alexander06 @  19.5.2008,  00:04 Найти цитируемый пост)
В возвращаемом значении согласно описанию - число принятых байт.

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

Цитата(Alexander06 @  19.5.2008,  00:04 Найти цитируемый пост)
Не могу понять..если данные приходят неравномерно, то должен же таймаут заставлять ее ожидать прихода оставшейся части?

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

Это сообщение отредактировал(а) ptr - 19.5.2008, 05:46


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
Олег2005
Дата 19.5.2008, 08:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(ptr @  19.5.2008,  04:46 Найти цитируемый пост)
recv возвращает уже пришедшие данные вплоть до запрошенного объема,

Назначение recv() - копировать из приемного буфера модуля TCP то, что имеется в нем на момент обращения к функции.
Сколько в приемном буфере накапало с канального уровня - сие науке неизвестно - это сеть. 
Насчет таймаута.
По жизни у recv() cвоего таймаута нет - по вполне понятной причине - лишь некоторые стеки позволяют его устанавливать.
Значит, таймаут устанавливается внешней функцией - например select(). 
Она вообще никакого отношения к сети не имеет - и сколько там байтов и где - ей глубоко безразлично.
PM MAIL WWW MSN   Вверх
Arrowdodger
Дата 21.5.2008, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



может немного оффтоп, но такой вопрос - recv при вызове блокирует выполнение программы. 
а мне нужно чтобы если в буфере ничего нет то программа выполнялась дальше. как это сделать?
PM MAIL   Вверх
Олег2005
Дата 21.5.2008, 18:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Два варианта:
Первый:
Запускаем recv() с флагом MSG_PEEK 
Цитата

MSG_PEEK. Флаг, определяемый константой MSG_PEEK, позволяет просматривать размер входного буфера модуля транспортного уровня. Обычно после считывания данных из входной очереди они уничтожаются. При записи флага MSG_PEEK после выполнения функций recv() или recvfrom() данные из буфера входной очереди не стираются (т.е. при повторном вызове этих функций без флага снова возвращаются ранее просмотренные данные). Этот флаг используется, например, программами протокола FTP. Надо иметь в виду, что для протокола TCP за время между вызовами функций могут прйти дополнительные байты сообщения.

Или использовать  ioctlsocket(socket, FIONREAD, count) для той же цели.
Есть одно но - значение 0 в буфере может трактоваться по разному - или пришло 0 байтов или сервер закончил передачу и закрыл сокет
Второй вариант - самый лучший. 
Сделать операцию recv() асинхронной - те объявить сокет асинхронным при помощи того же ioctlsocket() и команды FIONBIO.
Тогда recv() можно запустить и она сразу вернет управление в программу, которую можно дальше продолжать.
Затем функцией select() через некоторое время проверить результат завершения recv()
  
PM MAIL WWW MSN   Вверх
Arrowdodger
Дата 22.5.2008, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



да, второй вариант ниче так, только вот насчет select():

у меня recv() стоит в бесконечном цикле вот так:

Код

while(1)
{
recv(...);
...
}


выходит я могу не вызывать select() позже, а просто дожидаться следующей итерации цикла?
PM MAIL   Вверх
Олег2005
Дата 23.5.2008, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Arrowdodger @  22.5.2008,  11:29 Найти цитируемый пост)
выходит я могу не вызывать select() позже, а просто дожидаться следующей итерации цикла?

Если recv() стоит в цикле, дожидаясь признака конца передачи (возврат 0) на блокирующем сокете, то использование селекта не дает ничего.

Это сообщение отредактировал(а) Олег2005 - 24.5.2008, 20:47
PM MAIL WWW MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




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


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

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