1

I'm developing a client/server program in C. The server send to a client a txt file, but the name is like corrupt. The content is good, only the name is not good.

Can someone tell me why? Thank you!

This is the code who send the file:

fd = open(appoggio1, O_RDONLY);
if (fd < 0) {
  fprintf(stderr, "unable to open '%s': %s\n", appoggio1, strerror(errno));
  exit(1);
}
while ((nread = read(fd, buffer2, sizeof(buffer2))) > 0) 
    {
        write(servers_fd, buffer2, nread);
            read(servers_fd,buffer2,sizeof(char));
    }

    printf("Trasmissione completata con successo\n\n");

    write(servers_fd,fine,strlen(fine)); 
    read(servers_fd,fine,strlen(fine));
close(fd);

This is the code who receive the file:

fd = open(nomefile, O_CREAT | O_WRONLY, 0755);

    if (fd < 0) 
    {
        fprintf(stderr, "errore open(): %s\n", strerror(errno));
        exit(errno);
    }
while ((nread = read(conn_fd, buffer, sizeof(buffer))) > 0)
{
    if(!strncmp(buffer,fine,7))
        break;        
    write(fd, buffer, nread);
    write(conn_fd,buffer,sizeof(char));
}
write(conn_fd,fine,strlen(fine));

}

7
  • Have you send filename first..? What is nomefile..? Commented Mar 2, 2015 at 10:40
  • yes, it is the name of the file. Commented Mar 2, 2015 at 10:42
  • 1
    In sender side, where is code for sending file name..? Commented Mar 2, 2015 at 10:44
  • Have you test with valgrind ? Have you done a network trace (tcpdump) to see where the problem is, on the server or on the client ? Commented Mar 2, 2015 at 10:46
  • 1
    Another problem with your code is that sizeof(buffer2) in the sender must be equal to sizeof(buffer) in the receiver. Otherwise the handshake (sending back a byte) will fail. To avoid this it is better to send the file size after the file name and don't do the handshake. On the receiver side, keep track of the bytes received so far and compare it to the number of expected bytes. You'll know when all the data has been received. Commented Mar 2, 2015 at 11:09

1 Answer 1

1

The problem is with your protocol.

You send the file and then the name. But the client has no way of knowing when the file ends and the name begins.

You can fix it by first sending the length of the name and then the actual name:

#include <arpa/inet.h>

// Write the file name with length marker
uint32_t nameLength = htonl(strlen(fine));
write(servers_fd, &nameLength, sizeof nameLength); 
write(servers_fd, fine, strlen(fine)); 

// Write the actual file.

And in the client:

#include <arpa/inet.h>

uint32_t nameLength;
read(conn_fd, &nameLength, sizeof nameLength);
nameLength = ntohl(nameLength);

read(conn_fd, fine, nameLength);
fine[nameLength] = '\0';  // Add nul-terminator to file name.

// Read the rest of the file

htonl and ntohl convert numbers to network byte order, enabling your code to work even if the client and server use different byte orders (big/little endianness).

Note: Unless you use a size marker for the actual file as well, the client won't know how big it is, and the connection will only be good for one file download.

Note2: I have ignored the possibility that the size and file names might be divided into more than one network packets.

Sign up to request clarification or add additional context in comments.

12 Comments

My compilator says "error: unknown type name ‘uint_32t". In what library uint_32t is?
Sorry, it should be uint32_t.
I think I'm very near to the solution! Thank you my friend! I have to send the name of the file, I understood! There is only one problem: "warning: passing argument 1 of ‘strlen’ makes pointer from integer without a cast [enabled by default] write(servers_fd, fine,strlen(nameLength)); .... if I change strlen(nameLength)) with strlen(fine) it works but the name of the file is "name" + "all the contents of the file". Where is the problem?
The file name is sent without the null terminator. You need to manually add the string terminator after reading the file name. See updated answer
I changed the mask and it works! thank you very much! you saved me!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.