| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > Прочитать все данные из сокета |
| Автор: azesmcar 19.3.2009, 08:40 |
| Нужно прочитать все что есть в буффере сокета, т.е. все что пришло на данный момент. Можно конечно сделать recv на 10000 байт и посмотреть что пришло, но как-то некрасиво...к тому же буффер ему тоже надо будет создавать большой..собственно как это сделать? |
| Автор: InvalidProperty 19.3.2009, 09:27 | ||||
Не скажу, что мой пример единственно правильный, но я делал следующим образом:
в этом примере протокол построен таким образом, что клиентская сторона должна отправлять знак CTERM - признак окончания сообщения. Буду очень рад, если кто-нибудь укажет мне на недочеты моего метода или, вообще, предложит что-то свое |
| Автор: GrayCardinal 19.3.2009, 16:19 | ||
| azesmcar, Лезем в opsuperlib, или просто смотрим функтяру :
(вертает количество байт, которые ща есть для чтения) в opsuperlib еще куча всего, рекомендую |
| Автор: azesmcar 19.3.2009, 16:26 | ||
я нашел ioctlsocket, но он только под виндоуз..ioctl его аналог под линукс или как? могу и макрос вставить в принципе для кроссплатформенности (ибо мне нужен кроссплатформенный код). InvalidProperty, посмотрим какие еще будут варианты |
| Автор: InvalidProperty 19.3.2009, 16:46 |
| azesmcar, да я весь уши |
| Автор: vinick 20.3.2009, 12:33 |
| ЕМНИП размер приемного буфера у сокета можно получить через getsockopt(...,SO_RECVBUF,...). Ну а потом на неблокируемом сокете читать число байт равное размеру буфера. В этом случае должен вычитываться весь буфер. Можно еще добавить select или иной механизм мультиплексирования чтобы в холостую не читать. Только не понятно зачем такое требование ? Ведь как-только в приемном буфере сокета появится место - сразу начнут поступать новые данные... это учебная задача? |
| Автор: azesmcar 20.3.2009, 12:41 | ||||||
как зачем? пришли данные, которые мне нужно прочитать...сколько мне читать если я не знаю сколько их там?
и что? у меня протокол с нефиксированным размером сообщений, мне нужно прочитать все что пришло..
похоже? |
| Автор: vinick 20.3.2009, 12:41 |
| InvalidProperty, EINTR возвращается если системный вызов был прерван до того как прочитан хотя бы один байт. Так что lseek у тебя не имеет смысла. |
| Автор: Олег2005 20.3.2009, 15:42 | ||
TCP-потоковый протокол - и он совершенно не знает, что он передает - это труба, в которую что-то выливают на другом конце - от 1-го байта до более 4 гигов Разбираться должен с содержимым протокол верхнего уровня (как это делает например HTTP- парсит полученные данные и выуживает инфу.) - т.е. ваше приложение. А потому есть только конец TCP-сессии - recv() возвращает 0. |
| Автор: InvalidProperty 20.3.2009, 15:50 |
| Олег2005, итого, имеем, что кроме того, что я уже описал http://forum.vingrad.ru/index.php?showtopic=251879&view=findpost&p=1816608, ничего, в принципе, кардинально нового придумать нельзя. |
| Автор: azesmcar 20.3.2009, 16:05 |
| Олег2005, в принципе уже решил..добавляю в буффер пока не наберется нужный размер сообщения, как наберется отдаю обработчику..просто хотелось немного оптимизировать..если не дошло все сообщение, подождать что ли |
| Автор: Олег2005 20.3.2009, 16:10 |
| InvalidProperty, Примерно так azesmcar, К сожалению, оптимизировать работу модулей стека - это не наша задача! Они написаны и работают так, как написано в RFC. Честно говоря, они справляются и пока мы не жалуемся - чему свидетельство и эти диалоги. |
| Автор: vinick 20.3.2009, 16:13 | ||
Это не оправдание Тебе нужно прочитать сообщение или содержимое внутреннего буфера сокета ? Это две совершенно разные и малосвязанные между собой вещи. Читай небольшими кусками, как сазал Олег2005, тебе все равно придется как-то буферизовать поток и дробить его на сообщения на прикладном уровне.
В том смысле, что придется каким-то образом разграничивать сообщения на прикладном уровне, действительно ничего нового не придумаешь. Но самих способов разграничения можно придумать воз и маленькую тележку, и они могут кардинально различаться. |
| Автор: InvalidProperty 20.3.2009, 16:33 | ||
комрад, дык это ессесно. |
| Автор: azesmcar 20.3.2009, 18:28 | ||||||||
я говорил не о работе стека, а о том чтобы не читать по нескольку раз.
Я никогда и ни перед кем не оправдываюсь..
а в содержимом внутреннего буфера сокет что если не сообщение?
я не утверждал обратного, но "как-то" может быть быстро и медленно. Мне желательно сделать быстро..во всяком случае насколько это возможно. |
| Автор: vinick 20.3.2009, 18:46 | ||
Там может быть 1 сообщение, 10 сообщений, половина сообщения, конец первого сообщения и начало второго. в общем там может быть что угодно.
Если у тебя не InfiniBand, то скорость передачи по сети на порядки будет отставать от самого медленного метода извлечения сообщения из сокета. Так что особый фанатизм в такой оптимизации ИМХО излишен. Попробуй, добавлять перед сообщением его длинну. Пара-тройка байт особой погоды в передаваемом объеме не сделают, а вытаскивать сообщения будет гораздо удобнее, да и быстрее, чем ловить маркер конца сообщения. |
| Автор: azesmcar 20.3.2009, 19:08 | ||||||
мне все равно, они парсятся в очередь конкретных сообщений..
задержка на извлечении одного сообщения - задержит обработку, а следовательно и ответ на сообщение другого пользователя. Так что не совсем излишен. Правда речь не о фанатизме, если не найду другого способа, сделаю как знаю.
У меня так и сделано. Но если в заголовке написано что сообщение длиной в 30Кб, это не значит что я прочитаю их все. Я просто не хочу читать маленькими кусками. Уже написал класс для буфферизации сообщений..читаю сколько нужно, если в буффере недостаточно (recv вернул меньше чем нужно) жду следующего события. Как наберется - конвертирую в сообщение, передаю обработчику. |