LinuxForum.Fans
Тема

Реализация протокола FTP

Автор: lamazavr 11 сообщений 3305 просмотров
#111248

Не так давно получил задание написать ФТП клиент, естественно никакими лишними библиотеками мне пользоваться не разрешили wink
Проблема у меня состоит в следующем:
при запросе файла на скачивание сервер возвращает строку с его размером в байтах. Я по привычке решил выудить её при помощи функции sscanf предварительно разобрав строку до необходимого участка:

text
    char str[512];
    sprintf(str,"RETR %s\r\n",file);
    send(s,str,strlen(str),0);

/* получение строки с размером */ char size[512]; recv(s,size,512,0); cout << size; /* "обрезка" строки до необходимой части */ char *tmp_size; tmp_size = strtok(size,"("); tmp_size = strtok(NULL,"("); tmp_size = strtok(tmp_size, ")"); tmp_size = strtok(tmp_size, " ");

int file_size; sscanf(tmp_size,"%d",file_size);

cout << file_size;

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

зы таким же образом получал адрес для конекта соединения данных. всё норм oO

#111249

sscanf(tmp_size,"%d",&file_size);

Проблема в том, что sscanf пытается записать по адресу, переданному в третьем параметре. Туда было передано в качестве адреса произвольное _значение_ переменной file_size (а не её адрес), sscanf попыталась записать по этому адресу. Так что "Ошибка сегментирования" в этом случае -- вполне безболезненный вариант, хуже, когда запись молча происходит в произвольное место сегмента данных (например, начальное значение file_size оказалось бы равным tmp_size или адресу ещё какой-нибудь нужной переменной :-) ).

ps. Привет агитирующим за использование C/C++ в качестве первого языка для обучения программированию :-)

#111364

bormant, спасибо smile Ато уже не знал что и делать :rolleyes:

зы самое интересное, что выше на 20 строчек в коде я обращался правильно..

#116054

Столкнулся с интересным фактом!
При закачке файла сервер даёт понять что передаваться будет в бинарном формате (бинари дата моде конекшн и тп...)
В win и писать файл нужно соответственно бинарный, а в linux`e пишется обычный текстовый файл и всё ок oO
Почему так происходит?

#116090
"http://www.opennet.ru/man.shtml?topic=fopen&category=3&russian=0" написал:

#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
FILE *fdopen(int fildes, const char *mode);
FILE *freopen(const char *path, const char *mode, FILE *stream);
...
Строка mode может также включать в себя символ ``b'' в качестве последнего символа или символа, входящего в любые описанные выше двухсимвольные комбинации. Это требование является строгим только в случае, если требуется совместимость этой версии с ANSI X3.159-1989 (``ANSI C''); символ ``b'' игнорируется во всех POSIX-совместимых системах, включая Linux. Другие системы могут иначе обращаться к текстовым и бинарным файлам, и добавление ``b'' может оказаться полезным, если Вы осуществляете ввод-вывод в двоичный файл; возможно, Ваша программа будет когда-нибудь работать с не-Unix окружением.

В Linux конец строки представлен \n, а в Windows парой \r\n. В текстовом режиме эта \r из пары прозрачно выкидывается при чтении, а также прозрачно добавляется при записи \n.

Как-то так.

#116108
bormant написал:
Привет агитирующим за использование C/C++ в качестве первого языка для обучения программированию :-)

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

lamazavr написал:
В win и писать файл нужно соответственно бинарный, а в linux`e пишется обычный текстовый файл и всё ок blink
Почему так происходит?

а в Linux нет бинарных/двоичных, там просто файлы.

bormant написал:
В Linux конец строки представлен \n, а в Windows парой \r\n. В текстовом режиме эта \r из пары прозрачно выкидывается при чтении, а также прозрачно добавляется при записи \n.

Как-то так.

это так в венде. В линуксе какой режим не выбирай,

#116145

Про POSIX-совместимые (к которым относится и Linux) было сказано в цитате.
Про пару \r\n только в Windows -- тоже (очевидно, что поддержание этой пары к ней только и относится).

Для полноты картины стоило бы упомянуть Mac-и с их \r в качестве разделителя строк -- но тут вынужден апеллировать к обладателям таковых -- как там сейчас обстоят дела с концами строк в fprintf(fd, "\n") и в полученном файле?

#119690

и снова обращаюсь к знатокам)
сейчас занимаюсь функцией аплоада..

читаю из файла но почему то не до конца..

text
FILE *file;
file = fopen(fileName,"r");

while(!feof(file)){ char buff[128]; fread(&buff,sizeof(buff),1,file); send(ds,buff,strlen(buff),MSG_WAITALL); }

Причём замечено, что чем меньше буфер для чтения тем большее количество данных передано!
в чём может быть проблема?

#119723
lamazavr написал:
sizeof(buff)

размер массива считается sizeof(buff)/sizeof(buff[0])
почему вы не проверяете возвращаемое значение? почему вы читаете РОВНО 128 байт?
и наконец, почему вы отправляете 128 байт, даже не проверив, сколько байт прочиталось?
где определение ds?

#119772

проверки не делал для сокращения))

отправляю я не 128 байт! а ровно столько сколько попало в буфер) Размер указывается при помощи strlen()

по поводу почему 128: пальцем в небо! Есть какието рекомендации о размерах буфера?

#119867

lamazavr,
почему? Потому что не читаете документацию, в данном случае man fread, man strlen.

size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

fread читает nitems элементов, каждый размером size, из потока stream в *ptr; возвращает количество прочитанных элементов.

Вы используете вызов
fread(&buff, sizeof(buff), 1, file);
то есть пытаетесь читать по 1 элементу размером в 128 байт.

Если в file осталось <128 байт, элемент не может быть прочитан, возвращаемое значение 0, содержимое buff не изменено. Не в этом ли причина?

Кроме того, почему-то Вас совершенно не интересует, сколько же элементов было прочитано из потока.

Кроме того, используя strlen(), как Вы думаете, кто же записал завершающий \0 в buff, и почему Вы так думаете? Что происходит, когда из файла прочитан 1 объект в 128 байт целиком, что возвращает strlen(), как это соотносится с тем, что должно происходить? Не в этом ли причина?

Войдите или зарегистрируйтесь, чтобы ответить.