简体   繁体   中英

Send a File with socket in C for Linux

I'm writing a small and simple server (in C language for Linux stations).

A client requests a file to my server, my server asks this file to another server which sends it to my server.

My server should NOT receive ALL the file before sending it to the client BUT must send the bytes of the file so as they arrive.

This is an exercise in school so I can not dissociate myself from this requirement.

I have implemented the function explained below. The problem is that the client receives a non-deterministic number of bytes and NEVER the entire file.

int Recv_and_send_file (int socketa, int socketb, char *buffer, size_t file_size){

    size_t n;

    ssize_t nread;

    ssize_t nwritten;

    char c;

    for (n=1; n<file_size; n++)
    {        
            nread=recv(socketa, &c, 1, 0);

            if (nread == 1)
            {
                nwritten = send(socketb,&c,1,0);
            }
            else if (nread == 0)
            {
                *buffer = 0;
                return (-1); /* Errore */
            }
            else
                return (-1); /* Errore */
            }
    }
    *buffer = 0;
    return (n); 
}

Someone could kindly tell me where I'm wrong?

Is it an stupid idea to change the values ​​SO_SNDBUF and SO_RCVBUF on both the server and the client?

Assuming the file_size is the total number of bytes you want to send, then your for loop will only send file_size - 1 bytes. In other words, you are off by one. Start from 0 instead to fix this:

    for (n=0; n<file_size; n++)
    { //..

You capture the return value of send() , but you do not check to see if it was successful or not.

You are treating a 0 return value from recv() the same as an error. Since you do not show what you do after returning -1 from your function, I don't know if this may be contributing to your problem or not.

Certain errors on send() and recv() are "soft", in that you are allowed to retry the operation for those particular errors. One such error is EINTR , but check the documentation on your system to see if there are others.

In order to optimize performance and simplify your code, you can use splice()+pipes. Sendfile enables you to "forward" data between file descriptors, without the copy to user space.

Are you sure you have copied the correct code? That part as it is would not compile, there is a } in the last else which don't match with a corresponding {.

Also, how you get to know the file size? if it's send thru the socket as an integer, bear in mind the possible byte order of the source and destination machines.

Anyway, you are reading one byte at a time, you should improve it this way:

EDIT: use buffer and not the extra buff[2048];

int Recv_and_send_file (int socketa, int socketb, char *buffer, size_t file_size){

    ssize_t nread;
    ssize_t nwritten;
    ssize_t bLeft=file_size;

    while (bLeft > 0)
    {
        nread=recv(socketa, buffer, bleft, 0);
        if (nread > 0)
        {
            nwritten = send(socketb, buffer, nread, 0);
            bLeft -= nread;
            buffer+=nread;
        }
        else if (nread == 0)
        {
            // I think this could raise a memory exception, read below
            *buffer = 0;
            return (-1); /* Errore */
        }
        else
        {
            return (-1); /* Errore */
        }
    }
    // If buffer is allocated with file_size bytes this one will raise a memory exception
    // *buffer = 0;
    return (file_size-bLeft);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM