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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Прочитать все данные из сокета, как? 
V
    Опции темы
azesmcar
Дата 19.3.2009, 08:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



Нужно прочитать все что есть в буффере сокета, т.е. все что пришло на данный момент. Можно конечно сделать recv на 10000 байт и посмотреть что пришло, но как-то некрасиво...к тому же буффер ему тоже надо будет создавать большой..собственно как это сделать?

PM   Вверх
InvalidProperty
Дата 19.3.2009, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

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



Не скажу, что мой пример единственно правильный, но я делал следующим образом:

Код

#define CTERM 1

/* 
... 
*/

string buffer;
char    recv_line[MAXLINE + 1];
ssize_t n;

/* 
... 
*/

buffer.clear();
while( (n = _reads(connfd, recv_line, MAXLINE)) > 0)
{
 try
  { buffer += recv_line; }
 catch(exception)
 {
  printf("can not save data into buffer\n");
  return -1;
 }

 if(strchr(recv_line, CTERM) != NULL)                 // wait for term char
  break;
}
if(n == (ssize_t)-1)
 { printf("can not read from socket - %m"); return -1; }


Код

 ssize_t _reads(int fd, char* buff, size_t count)
 {
  ssize_t        n;

  if( (n = _read(fd, buff, count)) != (ssize_t)-1)
   buff[n] = 0;

  return n;
 }

 ssize_t _read(int fd, void* buff, size_t count)
 {
  ssize_t    n;
  off_t        offset;
  bool        is_pipe = false;

  if( (offset = lseek(fd, 0, SEEK_CUR)) == (off_t)-1)
  {
   if(errno != ESPIPE)
    return (ssize_t)-1;
   else
    is_pipe = true;
  }

 read_again:
  if( (n = read(fd, buff, count)) == (ssize_t)-1)
  {
   /* interrupted system call => return file position to that place, where we have stopped */
   if(errno == EINTR)
   {
    if(!is_pipe)
     if(lseek(fd, offset, SEEK_SET) == (off_t)-1)
      return (ssize_t)-1;
    goto read_again;
   }
  }

  return n;
 }


в этом примере протокол построен таким образом, что клиентская сторона должна отправлять знак CTERM - признак окончания сообщения.

Буду очень рад, если кто-нибудь укажет мне на недочеты моего метода или, вообще, предложит что-то свое


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
GrayCardinal
Дата 19.3.2009, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Фигасе
****


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

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



azesmcar, 
Лезем в opsuperlib, или просто смотрим функтяру :
Цитата

__export int DIONREAD (int fd)
{
    int ret = -1;
    if (ioctl (fd, FIONREAD, &ret) != 0)
  return -1;
    return ret;
}

(вертает количество байт, которые ща есть для чтения)

в opsuperlib еще куча всего, рекомендую smile





--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 19.3.2009, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



Цитата

Лезем в opsuperlib, или просто смотрим функтяру :


я нашел ioctlsocket, но он только под виндоуз..ioctl его аналог под линукс или как? могу и макрос вставить в принципе для кроссплатформенности (ибо мне нужен кроссплатформенный код).
InvalidProperty, посмотрим какие еще будут варианты smile
PM   Вверх
InvalidProperty
Дата 19.3.2009, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

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



azesmcar, да я весь уши  smile 


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
vinick
Дата 20.3.2009, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ЕМНИП размер приемного буфера у сокета можно получить через getsockopt(...,SO_RECVBUF,...). Ну а потом на неблокируемом сокете читать число байт равное размеру буфера.  В этом случае должен вычитываться весь буфер. Можно еще добавить select или иной механизм мультиплексирования чтобы в холостую не читать.

Только не понятно зачем такое требование ? Ведь как-только в приемном буфере сокета появится место - сразу начнут поступать новые данные... это учебная задача?


PM MAIL ICQ Jabber   Вверх
azesmcar
Дата 20.3.2009, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



Цитата

Только не понятно зачем такое требование?


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

Цитата

Ведь как-только в приемном буфере сокета появится место - сразу начнут поступать новые данные

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

Цитата

это учебная задача?

похоже? smile
PM   Вверх
vinick
Дата 20.3.2009, 12:41 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



InvalidProperty,  EINTR возвращается если системный вызов был прерван до того как прочитан хотя бы один байт. Так что lseek у тебя не имеет смысла.
PM MAIL ICQ Jabber   Вверх
InvalidProperty
Дата 20.3.2009, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

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



Цитата

EINTR
    Системный вызов был прерван сигналом до того, как был прочитан хотя бы один байт. 

да, ступил я чего-то. Сенкс, vinick

Добавлено через 10 минут и 18 секунд
Цитата(vinick @  20.3.2009,  12:33 Найти цитируемый пост)
Ведь как-только в приемном буфере сокета появится место - сразу начнут поступать новые данные...

Откуда? А если их никто больше не передает и на том конце клиент ждет, когда придет ответ?

Цитата(vinick @  20.3.2009,  12:33 Найти цитируемый пост)
ЕМНИП размер приемного буфера у сокета можно получить через getsockopt(...,SO_RECVBUF,...). Ну а потом на неблокируемом сокете читать число байт равное размеру буфера. В этом случае должен вычитываться весь буфер.

А как узнать, что в данный момент в буфере находится целое сообщение, а не его кусок? Я понимаю, что ТС это не учитывает по роду задачи, но мне интересно, как справиться с получением целого сообщения, если его длина неизвестна

Это сообщение отредактировал(а) InvalidProperty - 20.3.2009, 13:41


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
Олег2005
Дата 20.3.2009, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(InvalidProperty @  20.3.2009,  12:39 Найти цитируемый пост)
А как узнать, что в данный момент в буфере находится целое сообщение, а не его кусок? Я понимаю, что ТС это не учитывает по роду задачи, но мне интересно, как справиться с получением целого сообщения, если его длина неизвестна

TCP-потоковый протокол - и он совершенно не знает, что он передает - это труба, в которую что-то выливают на другом конце - от 1-го байта до более 4 гигов
Разбираться должен с содержимым протокол верхнего уровня (как это делает например HTTP- парсит полученные данные и выуживает инфу.) - т.е. ваше приложение.
А потому есть только конец TCP-сессии - recv() возвращает 0.


Это сообщение отредактировал(а) Олег2005 - 20.3.2009, 15:43
PM MAIL WWW MSN   Вверх
InvalidProperty
Дата 20.3.2009, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

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



Олег2005, итого, имеем, что кроме того, что я уже описал выше, ничего, в принципе, кардинально нового придумать нельзя. 

Это сообщение отредактировал(а) InvalidProperty - 20.3.2009, 15:53


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
azesmcar
Дата 20.3.2009, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



Олег2005, в принципе уже решил..добавляю в буффер пока не наберется нужный размер сообщения, как наберется отдаю обработчику..просто хотелось немного оптимизировать..если не дошло все сообщение, подождать что ли smile
PM   Вверх
Олег2005
Дата 20.3.2009, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



InvalidProperty, 
Примерно так smile 
azesmcar, 
К сожалению, оптимизировать работу модулей стека - это не наша задача!
Они написаны и работают так, как написано в RFC.
Честно говоря, они справляются и пока мы не жалуемся - чему свидетельство и эти диалоги.

Это сообщение отредактировал(а) Олег2005 - 20.3.2009, 16:11
PM MAIL WWW MSN   Вверх
vinick
Дата 20.3.2009, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(azesmcar @  20.3.2009,  12:41 Найти цитируемый пост)
и что? у меня протокол с нефиксированным размером сообщений, 

Это не оправдание smile


Цитата(azesmcar @  20.3.2009,  12:41 Найти цитируемый пост)
мне нужно прочитать все что пришло..

Тебе нужно прочитать сообщение или содержимое внутреннего буфера сокета ? Это две совершенно разные и малосвязанные между собой вещи. Читай небольшими кусками, как сазал Олег2005, тебе все равно придется как-то буферизовать поток и дробить его на сообщения на прикладном уровне.


Цитата(InvalidProperty @  20.3.2009,  15:50 Найти цитируемый пост)
имеем, что кроме того, что я уже описал выше, ничего, в принципе, кардинально нового придумать нельзя. 

В том смысле, что придется каким-то образом разграничивать сообщения на прикладном уровне, действительно ничего нового не придумаешь. Но самих способов разграничения можно придумать воз и маленькую тележку, и они могут кардинально различаться. 
PM MAIL ICQ Jabber   Вверх
InvalidProperty
Дата 20.3.2009, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

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



Цитата(vinick @  20.3.2009,  16:13 Найти цитируемый пост)
... самих способов разграничения можно придумать воз и маленькую тележку, и они могут кардинально различаться.

комрад, дык это ессесно. smile


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




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


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

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