[winsock] recv с таймаутом

olega

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

katrin2201

select ?

olega

Да, я думал о select. Но мне ситуация видится так. Вот я вызываю select он говорит, что есть данные для чтения. Но ведь не факт, что их хватит, чтобы заполнить мой буфер. Значит надо опять же реализовывать цикл, в цикле делать select/read и при этом наблюдать, не пропустили ли мы таймаут. То есть почти то же самое, что я предложил в первом посте. А хочется как-то без цикла обойтись...

vall

либо select и неблокирующийся recv, либо блокирующийся recv и сигнал от таймера который разблокирует по таймауту.

olega

Что-то я туплю.
либо select и неблокирующийся recv
Как?
либо сигнал от таймера который разблокирует по таймауту
Не дашь ссылки на соответствующие winapi функции?

elenangel

тебе так принципиально, чтобы нужное количество данных набралось именно в системном буфере?
вычитывай по столько, по сколько приходит и собирай в свой буфер, как только накопится необходимое количество - обрабатывай.

elenangel

вообще, вот (ioctlsocket) похоже на то, что тебе нужно

vall

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

olega

Вот какую магию нашел:

SO_RCVTIMEO
The timeout, in milliseconds, for blocking receive calls. The default for this option is zero, which indicates that a receive operation will not time out. If a blocking receive call times out, the connection is in an indeterminate state and should be closed.
If the socket is created using the WSASocket function, then the dwFlags parameter must have the WSA_FLAG_OVERLAPPED attribute set for the timeout to function properly. Otherwise the timeout never takes effect.
Осталось проверить, сработает ли.

elenangel

если не по таймауту придет немного байтов, как их обратно запихивать будешь?

olega

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

vik1538

Самое простое и правильное решение это select с recv в цикле.
select нужен затем, чтобы процессор не молотил цикл в пустую.
Что такое SO_RCVTIMEO точно не знаю, но думаю это настройка таймаута индикации ошибки при работе с оверлаппед сокетом. В общем, явно не то, что тебе нужно.

olega

Что такое SO_RCVTIMEO точно не знаю,
Но оно работает как надо, тем не менее :)
Оставить комментарий
Имя или ник:
Комментарий: