2013-03-29 4 views
2

Позвольте мне начать с того, что это домашнее задание, и я не программист на c. Я работаю над этим несколько дней, и я застрял. Я прочитал руководство beej от обложки до крышки и искал google в течение недели, пришло время обратиться за помощью. У меня есть приложение TCP-сокета клиент-сервер, которое отправляет и получает сообщения, как ожидалось, теперь мне нужно реализовать простую функцию загрузки/загрузки файлов.c socket file transfer

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

Клиент подключается неблокирующим сокетом с помощью команды выбора.

Я знаю, что есть много возможностей для улучшения, но может кто-то помочь мне начать?

// Сервер

void put (int sockfd, char *localfile) { 

    // Get file Size 
    FILE *file; 
    int size; 

    file = fopen(localfile, "rb"); 
    fseek(file, 0, SEEK_END); 
    size = ftell(file); 
    fseek(file, 0, SEEK_SET); 

    //Send file Size 
    write(sockfd, &size, sizeof(int)); 

    //Send file as Byte Array 
    char send_buffer[size]; 

    memset(send_buffer, 0, sizeof(send_buffer)); 
    //while(!feof(file)) { 
    // fread(send_buffer, 1, sizeof(send_buffer), file); 
    // write(sockfd, send_buffer, sizeof(send_buffer)); 
    // memset(send_buffer, 0, sizeof(send_buffer)); 
    //} 

    int sent; 

    while((sent = fread(send_buffer, sizeof(char), sizeof(send_buffer), file)) > 0) 
    { 
     if(send(sockfd, send_buffer, sent, 0) < 0) 
     { 
      fprintf(stderr, "[Server] ERROR: Failed to send file %s. (errno = %d)\n", localfile, errno); 
      break; 
     } 
     memset(send_buffer, 0, sizeof(send_buffer)); 
    } 
    fclose(file); 
} 

// Клиент

void get(int sockfd, char *remotefile) { 

    FILE *file; 
    int size; 

    //Read file Size 
    read(sockfd, &size, sizeof(int)); 

    //Read file Byte Array 
    char p_array[size]; 
    memset(&p_array, 0, sizeof(p_array)); 

    read(sockfd, p_array, size); 

    //Convert it Back into file 
    file = fopen(remotefile, "wb"); 
    fwrite(p_array, 1, sizeof(p_array), file); 
    fclose(file); 
} 
+0

Просто предостережение, прочитайте [этот поток StackOverflow] (http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong), чтобы узнать, как правильно использовать 'feof()'. –

+0

Может ли быть простой случай, когда вы не инициализируете свои массивы типа 'char send_buffer [size] = {0};' и 'char p_array [size] = {0};'? –

ответ

3

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

Ваш цикл отправки не делает эту ошибку. Итак, используйте это как модель, но повторите ее для получения, чтобы использовать read() вместо fread(). Затем вы должны увидеть, что нет необходимости выделять буфер размером файла, и поэтому нет необходимости отправлять файлы перед файлом, если вы не планируете поддерживать соединение открытым для другой цели.

Также нет причин для звонков memset().

+1

EJP, спасибо за ответ. Я не думаю, что понял ваши советы. Я изменил код следующим образом, но теперь все, что я получаю, это 4 байтовый файл с только непечатаемыми символами и \ 00 \ 00 – user2176271

+0

'void put (int sockfd, char * localfile) { // Получить файл Размер FILE * file; int size; file = fopen (localfile, "rb"); fseek (файл, 0, SEEK_END); size = ftell (файл); fseek (файл, 0, SEEK_SET); написать (sockfd, & size, sizeof (int)); char send_buffer [размер]; int sent; \t в то время как ((посланный = чтение (sockfd, send_buffer, размер))> 0) { , если (отправка (sockfd, send_buffer, отправленная, 0) <0) { fprintf (STDERR, «[Сервер] ОШИБКА : Не удалось отправить файл% s.(Ошибка =% d) \ п», лок_файл, ERRNO); перерыв; } } fclose (файл); }' – user2176271

+0

недействительных прибудут (интермедиат sockfd, символ * уд_файл) { \t FILE * файл; размер \t ИНТ; \t \t // Читаем файл Размер \t чтения (sockfd, и размер, SizeOf (INT)); \t \t // Читаем файл Байт Массив \t символ p_array [размер]; \t \t int bytes_read; \t // читаем (sockfd, p_array, size); \t в то время как ((bytes_read = чтение (sockfd, p_array, размер))> 0) \t { \t \t, если (RECV (sockfd, p_array, SizeOf (p_array), 0) <0) \t \t { \t \t \t fprintf (stderr, "[Client] ОШИБКА: Не удалось вернуть файл% s. (Errno =% d) \ n", remotefile, errno); \t \t \t break; \t \t} \t} \t \t // преобразовать его обратно в файл \t файл = Еореп (уд_файл, "термометр"); \t fwrite (p_array, 1, sizeof (p_array), файл); \t fclose (файл); } – user2176271