2011-12-30 4 views
3

Я пишу простой FTP-сервер для школьного проекта. Проект почти завершен, единственная проблема, с которой я столкнулся, - отправить файл через сокет клиенту. Я не могу записать в сокет более 200 килобайт данных, небольшие файлы загружаются успешно. Может ли кто-нибудь сказать мне, что является правильным способом отправки больших файлов через сокеты Linux?Отправить большие файлы через сокет в C

Заранее спасибо.

PS Я использую C и 32-разрядный Linux, сервер, работающий в режиме PORT, использовал функции открытия, записи, чтения и других функций низкого уровня, такие как sendfile, send, sendto.

+0

Можете ли вы показать нам какой-нибудь код? Почему вы не можете написать более 200 кб? –

+0

Если проект не требует, чтобы вы использовали сокеты напрямую, простой способ - реализовать ваш сервер с помощью libcurl (google it). –

+0

Какой клиент вы используете? Это когда сервер получает или отправляет файл? –

ответ

4

Одна идея может быть чтение файла кусок на кусок, что-то вроде:

Псевдо-код

#define CHUNK_SIZE 1000 

void send(){ 
    uint8_t buff[CHUNK_SIZE]; 
    int actually_read; 
    while((actually_read = read(fd, buff, sizeof(buff)) > 0) 
    sendto(sock_fd, buff, actually_read, 0); 
} 

Вы должны добавить некоторые проверки ошибок, но идея состоит в том, чтобы прочитать значительное количество байтов из файла, который вы хотите отправить и отправить эту сумму. На стороне сервера вам нужно сделать аналогичную вещь, читая из сокета поступающие куски и записывая их в файл. Возможно, вы захотите префикс некоторых метаданных до buff, чтобы сообщить серверу, какой файл вы передаете, если хотите обрабатывать несколько передач файлов. Поскольку FTP использует TCP, вы не должны беспокоиться о потере данных.

Опять же, это всего лишь идея. Есть несколько способов сделать это, я полагаю.

+1

Попробуйте размер фрагмента размером более 4096 байт, так как это стандартный размер страницы для чтения/записи Linux. Поэтому, если вы будете использовать буфер размером более 4096 байт, вы бы избежали потери производительности для 4 дополнительных системных вызовов. – DipSwitch

+0

Я попробую это, в любом случае я собираюсь попробовать свой сервер в другом дистрибутиве Linux – user1122920

3

вы можете MMAP файл и записать его на сокете оттуда, вы также можете получить его размер с помощью fstat, как это:

fd = open(filename, O_RDONLY); 
struct stat s; 
fstat(fd, &s); // i get the size 
adr = mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0); // i get the adress 
write(socket, adr, s.st_size); // i send the file from this adress directly 

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