Mukesh Gupta Mukesh Gupta - 3 months ago 15
C Question

File transfer from client to server

I am trying to send a file from client to server. It sometime worksand sometime don't. when first time trying to send file, it sends corrupt file and the file side formed at server side is double of its size. But file successful transfers for all attempts after first attempt. Can anyone help me with this ?

Client.c

message msg;
msg.type = SEND_FILE;
char *username, *filename;

username = strtok(input+6, " ");
filename = strtok(NULL, "");

//Get Picture Size
printf("Getting Picture Size\n");
FILE *picture;
picture = fopen(filename, "r");
int size;
fseek(picture, 0, SEEK_END);
size = ftell(picture);
fseek(picture, 0, SEEK_SET);

//Send Picture Size
printf("Getting Picture Size\n");
sprintf(msg.data, "%d", size);
strncpy(msg.username, username, 20);

if(send(connection->socket, &msg, sizeof(message), 0) < 0)
{
perror("Send failed");
exit(1);
}
//Send Picture as Byte Array
printf("Sending Picture as Byte Array\n");
char send_buffer[size+1];
fread(send_buffer, 1, sizeof(send_buffer), picture);
write(connection->socket, send_buffer, sizeof(send_buffer));
bzero(send_buffer, sizeof(send_buffer));


server.c

//Read Picture Size
printf("Reading Picture Size\n");
int size = atoi(message_text);

//Read Picture Byte Array
printf("Reading Picture Byte Array\n");
char p_array[size];
printf("Converting Byte Array to Picture %d\n", size);
FILE *image;
image = fopen("c4.png", "w");
int readSize = 0;
while (readSize < size) {
readSize = readSize + read(clients[sender].socket, p_array, size);
fwrite(p_array, 1, sizeof(p_array), image);
}

fclose(image);

alk alk
Answer

For starters:

You don't want to store the same number of bytes on every fwrite()

fwrite(p_array, 1, sizeof(p_array), image);

but only the number of bytes actually read.

sizeof(p_array) returns the size of p_array, which is size times the size of a char. The latter is defined as being 1.


Besides this the call to read() completely lacks error checking, along with the test whether the other side shut down the connection. This is not leading far.


To fix this you could do:

#include <errno.h> /* for errno */

...

  size_t size = atoi(message_text);
  printf("Reading Picture Byte Array\n");
  char p_array[size];
  size_t readSize = 0;
  while (readSize < size) {
    ssize_t result = read(clients[sender].socket, p_array, size); /* Mind the ssize_t, it's *not* size_t! */
    if (0 >= result)
    {
      if (0 == result)
      {
        fprintf(stderr, "The other end gracefully shut down the connection.\n");

        break;
      }
      else
      {
        if (EINTR == errno)  /* got interrupted, start over */
        {
           continue;
        }

        if (EAGAIN == errno)  /* in case reading from a non-blocking socket: no data available, start over */
        {
           continue;
        }

        /* Something went wrong unrecoverable. */
        perror("read() failed");

        break;
      }
    }
    else
    {
       fwrite(p_array, 1, result, image); 
       /* Also add error checking here! */
       readSize += result;
    }
 }
Comments