2

Let me start by saying this is a homework assignment and I am not a c programmer. I have been working on this for days and I am stuck. I have read the beej guide from cover to cover and have been searching google for a week, it's time to ask for help. I have a client-server TCP socket application that sends and receives messages as expected, now I need to implement simple file upload/download functionality.

The code below almost works but it adds 4 bytes to the beginning of the copied file, two non-printable characters followed by \00\00 and the client no longer responds.

The client is connected by a non-blocking socket using the select command.

I know there is lots of room for improvement but can someone help me get started?

// Server

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);
}

//Client

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);
}
AndreyAkinshin
  • 18,603
  • 29
  • 96
  • 155
user2176271
  • 33
  • 1
  • 4
  • Just a warning, read [this StackOverflow thread](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong) to learn how to correctly use `feof()`. – Anish Ramaswamy Mar 29 '13 at 05:35
  • Could it be the simple case of you not initializing your arrays like `char send_buffer[size] = { 0 };` and `char p_array[size] = { 0 };`? – Anish Ramaswamy Mar 29 '13 at 05:57

1 Answers1

3

You are making the usual error of ignoring the read count when reading the socket, and assuming that each read fills the buffer. You can't assume that.

Your send loop doesn't make that mistake. So, use that as a model, but redo it for receiving so as to use read() instead of fread(). You should then see that there's no need to allocate a buffer the size of the file, and there is therefore no need to send the filesize ahead of the file, unless you're planning on keeping the connection open for another purpose.

There's also no reason for any of the memset() calls.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    EJP, thank you for the reply. I don't think I understood your advice. I changed the code as follows but now all I get is a 4 byte file with only the non-printable characters and the \00\00 – user2176271 Mar 29 '13 at 03:56
  • `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); write(sockfd, &size, sizeof(int)); char send_buffer[size]; int sent; while((sent = read(sockfd, send_buffer, size)) > 0) { if(send(sockfd, send_buffer, sent, 0) < 0) { fprintf(stderr, "[Server] ERROR: Failed to send file %s. (errno = %d)\n", localfile, errno); break; } } fclose(file); }` – user2176271 Mar 29 '13 at 04:00
  • 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]; int bytes_read; //read(sockfd, p_array, size); while((bytes_read = read(sockfd, p_array, size)) > 0) { if(recv(sockfd, p_array, sizeof(p_array), 0) < 0) { fprintf(stderr, "[Client] ERROR: Failed to recv file %s. (errno = %d)\n", remotefile, errno); break; } } //Convert it Back into file file = fopen(remotefile, "wb"); fwrite(p_array, 1, sizeof(p_array), file); fclose(file); } – user2176271 Mar 29 '13 at 04:05
  • I'm sorry for the formatting, I can't figure out how to format code in a reply. – user2176271 Mar 29 '13 at 04:06
  • also, yes, I need to keep the connection open so the client can perform other operations after the file is uploaded/downloaded. – user2176271 Mar 29 '13 at 04:07
  • @user2176271 Posting code in comments is completely pointless. It is illegible, as you can see for yourself. Edit it into your question. However I can see that you still haven't done anything about using the read count returned by recv() when reading the socket. When you've tried it let us know. Until you do, further posts are futile. – user207421 Mar 31 '13 at 00:17