4

I want to program an application to send a file with sockets:

Here my Server:

   void str_server(int sock)
    {
            char buf[1025];
            const char* filename="test.text";
            FILE *file = fopen(filename, "rb");
            err_abort("Test");
            while (!feof(file))
            {
                int rval = fread(buf, 1, sizeof(buf), file);
                send(sock, buf, rval, 0);
            }
    }

and here my client:

void RecvFile(int sock, const char* filename)
{
    int rval;
    char buf[0x1000];
    FILE *file = fopen(filename, "wb");
    while ((rval = recv(sock, buf, sizeof(buf), 0)) > 0)
    {
        fwrite(buf, 1, rval, file);
    }
    close(sock);
}

My problem is that my client create a file....but dont write the content in the file!

1
  • As an aside, you dont need to read every byte and send it down the socket. You could read the entire string into a buffer and send(..) it at one go. About your problem, did you close the file before checking it? Commented Mar 26, 2012 at 17:02

1 Answer 1

9

Add some error handling to your code, that should help you track down the problem. Also note that send(), recv(), fread() and fwrite() are not guaranteed to write/read the entire buffer you specify, so you should take that into account as well.

Also, since TCP is a byte stream, the server needs to indicate when the file ends so the client knows when to stop reading. If you don't send the file size before sending the actual file, the only option is to close the socket when the transfer is done.

Try something like this:

int send_all(int sock, const void *buf, int len)
{
    const char *pbuf = (const char *) buf;

    while (len > 0)
    {
        int sent = send(sock, pbuf, len, 0);
        if (sent < 1)
        {
            // if the socket is non-blocking, then check
            // the socket error for WSAEWOULDBLOCK/EAGAIN
            // (depending on platform) and if true then
            // use select() to wait for a small period of
            // time to see if the socket becomes writable
            // again before failing the transfer...

            printf("Can't write to socket");
            return -1;
        }

        pbuf += sent;
        len -= sent;
    }

    return 0;
}

void str_server(int sock) 
{ 
    char buf[0x1000]; 
    const char* filename = "test.text";
    struct stat s;

    if (stat(filename, &s) == -1)
    {
        printf("Can't get file info"); 
        return;
    }

    FILE *file = fopen(filename, "rb"); 
    if (!file)
    {
        printf("Can't open file for reading"); 
        return;
    }

    // if you need to handle files > 2GB,
    // be sure to use a 64bit integer, and
    // a host-to-network function that can
    // handle 64bit integers...
    long size = s.st_size;
    long tmp_size = htonl(size);
    if (send_all(sock, &tmp_size, sizeof(tmp_size)) == 0)
    {
        while (size > 0)
        { 
            int rval = fread(buf, 1, min(sizeof(buf), size), file); 
            if (rval < 1)
            {
                printf("Can't read from file");
                break;
            }

            if (send_all(sock, buf, rval) == -1)
                break;

            size -= rval;
        }
    }

    fclose(file);
} 

int write_all(FILE *file, const void *buf, int len)
{
    const char *pbuf = (const char *) buf;

    while (len > 0)
    {
        int written = fwrite(pbuf, 1, len, file);
        if (written < 1)
        {
            printf("Can't write to file");
            return -1;
        }

        pbuf += written;
        len -= written;
    }

    return 0;
}

int read_all(int sock, void *buf, int len)
{
    char *pbuf = (char *) buf;
    int total = 0;

    while (len > 0)
    {
        int rval = recv(sock, pbuf, len, 0);
        if (rval < 0)
        {
            // if the socket is non-blocking, then check
            // the socket error for WSAEWOULDBLOCK/EAGAIN
            // (depending on platform) and if true then
            // use select() to wait for a small period of
            // time to see if the socket becomes readable
            // again before failing the transfer...

            printf("Can't read from socket");
            return -1;
        }

        if (rval == 0)
        {
            printf("Socket disconnected")
            return 0;
        } 

        pbuf += rval;
        len -= rval;
        total += rval;
    }

    return total;
}

void RecvFile(int sock, const char* filename) 
{ 
    int rval; 
    char buf[0x1000];

    FILE *file = fopen(filename, "wb"); 
    if (!file)
    {
        printf("Can't open file for writing");
        return;
    }

    // if you need to handle files > 2GB,
    // be sure to use a 64bit integer, and
    // a network-to-host function that can
    // handle 64bit integers...
    long size = 0;
    if (read_all(sock, &size, sizeof(size)) == 1)
    {
        size = ntohl(size);
        while (size > 0)
        {
            rval = read_all(sock, buf, min(sizeof(buf), size));
            if (rval < 1)
                break;

            if (write_all(file, buf, rval) == -1)
                break;
        } 
    }

    fclose(file); 
} 
Sign up to request clarification or add additional context in comments.

10 Comments

missing some statements at the end. The doWhileouter loop
so you just removed the outer loop? and changed the condition as well
why you removed offset? Seems will not work for larger files having len greater than buffer
@Saad The code still works for large files. The outer loops still exist to read files using fixed buffers. I just refactored the code to extract the inner loops to their own functions when writing each buffer to the target, and then the offset logic wasn't needed anymore.
still it doesn't skips the loop even after reading last bufer and keeps waiting to receive from socket.
|

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.