LINUX.ORG.RU

recv в переменую!


0

0

Во всех примерах по сокетам есть такой код:

if ((numbytes=recv(fd,buf,MAXDATASIZE,0)) == -1) { printf("recv() error\n"); exit(-1); }

buf[numbytes] = '\0'; printf("Server Message: %s\n",buf);

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

Т.е как я могу поместить в переменую все целеком, присланные данные из recv и правильно выделить память.

anonymous

считывай по байтово в цикле.

> а точный размер я могу получить только в recv,

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

nil5
()

>Но что делать если я не знаю сколько памяти мне нужно выделить в MAXDATASIZE

1)выделять с запасом

2)выделять по частям по мере вычитки

cvv ★★★★★
()
Ответ на: комментарий от Dead

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

Я вот так извратил не пашит.

#define STEP 1045 char buf[STEP];

char to[STEP]=""; while((numbytes = recv(sock, buf,sizeof(buf),0)) > 0) { if (numbytes == -1) {perror("numbytes"); exit(4);} if (strlen(to) == 0) strcpy(to,buf); else { realloc(to,strlen(to)+STEP); strcat(to,buf); } }

anonymous
()
Ответ на: комментарий от anonymous

ерунда какая-то
первое, что бросается в глаза
char to[STEP]  объявлен в стеке
но ты его пытаешься ресайзить используя функции работы с динамической памятью.

Dead ★★★★
()

вообще-то вы можете узнать, сколько данных есть
в сокете - ioctl(FIONREAD). но это плохой подход.

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

idle ★★★★★
()
Ответ на: комментарий от anonymous

>Я представляю что в букваре :)

сомневаюсь. ты ведь его не читал.

>char *to; Тоже не пашет.

и не должен

cvv ★★★★★
()

Надо работать со строками? fscanf или что-то родственное поможет? Тогда просто "переоткрой" сокет с помощью fdopen и используй стандартные функции из stdio.. Это чтобы не морочить никому голову.

PS. Это не по теме, просто стало интересно, производительность от таких манипуляций пострадает? И как лучше всего настроить буфер для сокета (с помощью setvbuf например) для улучшения произодительности (обмен только текстом)?

OxiD ★★★★
()
Ответ на: комментарий от idle

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

Chumka ★★★
()
Ответ на: комментарий от Chumka

> больше чем FIONREAD данных в сокете не будет.

почему же? сразу после возврата из ioctl() могут
появиться новые данные. это и по другим причинам
неуклюжее решение.

idle ★★★★★
()

Может быть использовать список, что-то вроде

#define BUF_SIZE 128
struct Node {
data char[BUF_SIZE];
int data_size;
Node *next;
}

И при чтении, если заполняется текущий узел - выделять новый. Большого перерасхода памяти не будет, скорость не постарадает, по-моему самое правильное решение.

Legioner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.