TCP sockets, send files, client server, server doest save a whole file, C language

Viewed 187

I wrote a simple protocol in which Im able to exchange files / text messages between client and server. If the client send a text to server, server should simply echo it back. On the other hand, when client send a special command (for example, SEND_TXT_FILE) server should receive a file uploaded by client to the server.

I almost got it work. However, there's still problem with sending files. Sever does not save the whole file, it only creates it and disconnects.

Here's the protocol:

CLIENT ---------- text1 ----------> SERVER
CLIENT <---------- text1 ---------- SERVER
CLIENT ---------- text2 ----------> SERVER
CLIENT <---------- text3 ---------- SERVER
CLIENT ---------- SENDTXTFILE ----------> SERVER
CLIENT <---------- OK ---------- SERVER
CLIENT ---------- FILENAME ----------> SERVER
CLIENT <---------- OK ---------- SERVER
CLIENT ---------- file content ----------> SERVER
CLIENT <--------- FILE_UPLOADED --------- SERVER
CLIENT ---------- text3 ----------> SERVER
CLIENT <---------- text3 ---------- SERVER

How can I solve this?

server.c

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>

#define BUFFER_SIZE 1024

int send_all(int sockfd, const char *buf, int len)
{
    ssize_t n;

    while (len > 0)
    {
        n = send(sockfd, buf, len, 0);
        if (n < 0)
            return -1;
        buf += n;
        len -= n;
    }

    return 0;
}

int recv_all(int sockfd, char *buf, int len)
{
    ssize_t n;

    while (len > 0)
    {
        n = recv(sockfd, buf, len, 0);
        if (n <= 0)
            return n;
        buf += n;
        len -= n;
    }

    return 1;
}

int recv_txt_file(int sockfd, int len, const char *filename)
{
    FILE *fp = fopen(filename, "wb");
    int total = 0, b = 0;
    char buffer[BUFFER_SIZE];
    memset(buffer, '\0', BUFFER_SIZE);

    if (fp != NULL)
    {
        while (recv_all(sockfd, buffer, len) != 1)
        {
            total += b;
            fwrite(buffer, 1, b, fp);
        }

        printf("Received byte: %d\n",total);
        if (b < 0)
            perror("Receiving");

        fclose(fp);
    }
    else
    {
        perror("File");
    }
    close(sockfd);
}

int main()
{
    int port = 6666;
    int server_fd, client_fd, read;
    struct sockaddr_in server, client;
    char buffer[BUFFER_SIZE], filename[BUFFER_SIZE];
    char remote_ip[16];
    int remote_port, res = 0;

    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0)
    {
        perror("Could not create socket");
        return 1;
    }

    int optval = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof(int));

    memset(&server, '\0', sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
        perror("Could not bind socket");
        close(server_fd);
        return 1;
    }

    if (listen(server_fd, 1) < 0)
    {
        perror("Could not listen on socket");
        close(server_fd);
        return 1;
    }

    printf("Server TCP is listening on port %d ... \n", port);

    socklen_t client_len = sizeof(client);
    client_fd = accept(server_fd, (struct sockaddr *)&client, &client_len);

    if (client_fd < 0)
    {
        perror("Could not establish new connection");
        close(server_fd);
        return 1;
    }

    remote_port = ntohs(client.sin_port);
    inet_ntop(AF_INET, &client.sin_addr, remote_ip, sizeof(remote_ip));

    printf("Client IP address: %s, port %d\n", remote_ip, remote_port);

    while (1)
    {
        read = recv_all(client_fd, buffer, BUFFER_SIZE);
        if (read <= 0)
        {
            if (read < 0)
                perror("Client read failed");
            else
                printf("Client disconnected\n");
            break;
        }

        if ((res = strcmp(buffer, "SENDFILE_TXT\n") == 0))
        {

            printf("-------FROM CLIENT: %s-------\n", buffer);
            memset(buffer, BUFFER_SIZE, '\0');
            strcpy(buffer, "OK");
            if (send_all(client_fd, buffer, BUFFER_SIZE) < 0)
            {
                perror("Client write failed");
                break;
            }
            read = recv_all(client_fd, buffer, BUFFER_SIZE);
            if (read <= 0)
            {
                if (read < 0)
                    perror("Client read failed");
                else
                    printf("Client disconnected\n");
                break;
            }
            printf("-------FROM CLIENT: %s-------\n", buffer);
            memset(filename, '\0', BUFFER_SIZE);
            strcpy(filename, buffer);
            memset(buffer, BUFFER_SIZE, '\0');
            strcpy(buffer, "OK");
            if (send_all(client_fd, buffer, BUFFER_SIZE) < 0)
            {
                perror("Client write failed");
                break;
            }
            recv_txt_file(client_fd, BUFFER_SIZE, filename);
        }
        else
        {
            printf("FROM CLIENT: %.*s\n", BUFFER_SIZE, buffer);

            if (send_all(client_fd, buffer, BUFFER_SIZE) < 0)
            {
                perror("Client write failed");
                break;
            }
        }
    }

    close(client_fd);
    close(server_fd);

    return 0;
}

client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#define BUFFER_SIZE 1024

socklen_t hostname_to_ip_port(char *hostname, int port, struct sockaddr_storage *addr)
{
    int sockfd;
    struct addrinfo hints, *servinfo;
    int rv;

    char service[20];
    sprintf(service, "%d", port);

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    if ((rv = getaddrinfo(hostname, service, &hints, &servinfo)) != 0)
    {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 0;
    }

    socklen_t addrlen = servinfo->ai_addrlen;
    memcpy(addr, servinfo->ai_addr, addrlen);

    freeaddrinfo(servinfo);

    return addrlen;
}

int send_all(int sockfd, const char *buf, size_t len)
{
    ssize_t n;

    while (len > 0)
    {
        n = send(sockfd, buf, len, 0);
        if (n < 0)
            return -1;
        buf += n;
        len -= n;
    }

    return 0;
}

int recv_all(int sockfd, char *buf, int len)
{
    ssize_t n;

    while (len > 0)
    {
        n = recv(sockfd, buf, len, 0);
        if (n <= 0)
            return n;
        buf += n;
        len -= n;
    }

    return 1;
}

long int get_file_size(char filename[])
{
    // opening the file in read mode
    FILE *fp = fopen(filename, "r");

    // checking if the file exist or not
    if (fp == NULL) {
        printf("File Not Found!\n");
        return -1;
    }

    fseek(fp, 0L, SEEK_END);

    // calculating the size of the file
    long int res = ftell(fp);

    // closing the file
    fclose(fp);

    return res;
}

int send_txt_file(int sockfd, int len, const char *filename)
{
    FILE *fp = fopen(filename, "r");
    int b;
    char buffer[BUFFER_SIZE];
    memset(buffer, '\0', BUFFER_SIZE);

    if (fp == NULL)
    {
        perror("Error while openning file");
        return 0;
    }

    while ((b = fread(buffer, 1, BUFFER_SIZE, fp)) > 0){
        send_all(sockfd, buffer, BUFFER_SIZE);
        memset(buffer, '\0', BUFFER_SIZE);
    }

    fclose(fp);
    return 1;
}

int main(int argc, char **argv)
{
    char *hostname = "127.0.0.1";
    int port = 6666;
    char buffer[BUFFER_SIZE], fname[BUFFER_SIZE];

    int sockfd, err, res;
    struct sockaddr_storage server_addr;
    socklen_t server_addr_len;

    server_addr_len = hostname_to_ip_port(hostname, port, &server_addr);
    if (server_addr_len == 0)
        return 1;

    sockfd = socket(server_addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
    if (sockfd < 0)
    {
        perror("Could not create socket");
        return 1;
    }

    if (connect(sockfd, (struct sockaddr *)&server_addr, server_addr_len) < 0)
    {
        perror("Could not connect socket");
        return 1;
    }

    while (1)
    {
        memset(buffer, BUFFER_SIZE, '\0');
        memset(fname, BUFFER_SIZE, '\0');

        printf("> ");
        if (!fgets(buffer, BUFFER_SIZE, stdin))
            break;

        if (strstr(buffer, "SENDFILE_TXT") != NULL)
        {
            if (send_all(sockfd, buffer, BUFFER_SIZE) < 0)
            {
                perror("Could not send message");
                close(sockfd);
                return 1;
            }

            memset(buffer, BUFFER_SIZE, '\0');
            err = recv_all(sockfd, buffer, BUFFER_SIZE);
            if (err <= 0)
            {
                if (err < 0)
                    perror("Could not read message");
                else
                    printf("Server disconnected\n");
                break;
            }
            if ((res = strcmp(buffer, "OK") == 0))
            {
                printf("-------FROM SERVER: %s-------\n", buffer);

                printf("Give filename> ");
                memset(fname, BUFFER_SIZE, '\0');
                if (!fgets(fname, BUFFER_SIZE, stdin))
                    break;
                if (send_all(sockfd, fname, BUFFER_SIZE) < 0)
                {
                    perror("Could not send message");
                    close(sockfd);
                    return 1;
                }
            }

            err = recv_all(sockfd, buffer, BUFFER_SIZE);
            if (err <= 0)
            {
                if (err < 0)
                    perror("Could not read message");
                else
                    printf("Server disconnected\n");
                break;
            }

            fname[strlen(fname)-1] = 0;
            printf("----%s----\n", fname);
            send_txt_file(sockfd, BUFFER_SIZE, fname);

            printf("FROM SERVER: %.*s\n", BUFFER_SIZE, buffer);
        }
        else
        {
            if (send_all(sockfd, buffer, BUFFER_SIZE) < 0)
            {
                perror("Could not send message");
                close(sockfd);
                return 1;
            }

            err = recv_all(sockfd, buffer, BUFFER_SIZE);
            if (err <= 0)
            {
                if (err < 0)
                    perror("Could not read message");
                else
                    printf("Server disconnected\n");
                break;
            }
            printf("FROM SERVER: %.*s\n", BUFFER_SIZE, buffer);
        }
    }

    close(sockfd);

    return 0;
}
2 Answers

The way you are using send_txt_file() and recv_txt_file() to transfer a file is not correct.


On the server side:

When a client connects, the server waits for the client to send exactly BUFFER_SIZE (1024) bytes for each command, no more, no less (which is a waste of bandwidth for short commands). When a SENDFILE_TXT command is received, the server reads the filename from the client (which will cause a buffer overflow if the filename is exactly BUFFER_SIZE bytes in length), and then calls recv_txt_file().

recv_txt_file() attempts to read from the client in a loop, reading in exactly BUFFER_SIZE chunks. However, the while loop being used is coded incorrectly. It is checking the return value of recv_all() for failure, not for success. The != check needs to be changed to == instead. And also, the b variable that is being used to increment total, and tell fwrite() how many bytes to write, is never set to any value other than 0. It needs to be set to BUFFER_SIZE instead, since that is how many bytes have actually been read if recv_all() returns 1.

However, even if the while loop were coded properly, the transfer would still not operate properly, because it requires the file to be sent in even multiples of BUFFER_SIZE. If the file is not an even multiple in size, recv_all() will end up waiting for data that the client does not send, until an error occurs on the socket.

Also, recv_txt_file() is closing the connection after the transfer is finished. It should not do that, as that will prevent the client from being able to send further commands after sending a file. The client is not closing its end of the connection after sending a file, so the server should not be closing its end after receiving a file.


On the client side:

When the client sends a SENDFILE_TXT command and gets an acknowledgement back, it calls send_txt_file(), which reads the file in a loop, sending it to the server in BUFFER_SIZE sized chunks. If the file size is not an even multiple of BUFFER_SIZE, the last block sent will just waste bandwidth and send random garbage to the server. Also, you are ignoring the return value of send_all() to break the loop if an error occurs on the socket.


The client should send the actual file size to the server before sending the file data. The server can then read that size value first so it knows when to stop reading.

That being said, try something more like the following:

server.c

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <stdint.h>

#define BUFFER_SIZE 1024

int send_all(int sockfd, const void *buf, int len)
{
    ssize_t n;
    const char *pbuf = (const char*) buf;

    while (len > 0)
    {
        n = send(sockfd, pbuf, len, 0);
        if (n < 0)
        {
            perror("Client write failed");
            return n;
        }
        pbuf += n;
        len -= n;
    }

    return 0;
}

int send_uint32(int sockfd, uint32_t value)
{
    value = htonl(value);
    if (send_all(sockfd, &value, sizeof(value)) < 0)
        return -1;
    return 0;
}

int send_str(int sockfd, const char *s)
{
    uint32_t len = strlen(s);
    int res = send_uint32(sockfd, len);
    if (res == 0)
        res = send_all(sockfd, s, len);
    return res;
}

int recv_all(int sockfd, void * buf, int len)
{
    ssize_t n;
    char *pbuf = (char*) buf;

    while (len > 0)
    {
        n = recv(sockfd, pbuf, len, 0);
        if (n <= 0)
        {
            if (n < 0)
                perror("Client read failed");
            else
                printf("Client disconnected\n");
            return n;
        }
        pbuf += n;
        len -= n;
    }

    return 1;
}

int recv_uint32(int sockfd, uint32_t *value)
{
    int res = recv_all(sockfd, value, sizeof(*value));
    if (res > 0)
        *value = ntohl(*value);
    return res;
}

int recv_uint64(int sockfd, uint64_t *value)
{
    int res = recv_all(sockfd, value, sizeof(*value));
    if (res > 0)
        *value = ntohll(*value); // <-- use any implementation of your choosing...
    return res;
}

int recv_str(int sockfd, char **str)
{
    uint32_t len;

    int res = recv_uint32(sockfd, &len);
    if (res <= 0)
        return res;

    *str = (char*) malloc(len + 1);
    if (*str == NULL)
    {
        perror("Could not allocate memory");
        return -1;
    }

    res = recv_all(sockfd, *str, len);
    if (res <= 0)
        free(*str);
    else
        (*str)[len] = '\0';

    return res;
}

int recv_txt_file(int sockfd)
{
    char *filename;
    uint64_t filesize;

    if (recv_str(sockfd, &filename) <= 0)
        return -1;

    int res = recv_uint64(sockfd, &filesize);
    if (res <= 0)
    {
        free(filename);
        return -1;
    }

    printf("-------FROM CLIENT: %s-------\n", filename);

    FILE* fp = fopen(filename, "wb");
    if (fp == NULL)
    {
        perror("Could not create file");
        free(filename);
        send_str(sockfd, "NO");
        return 0;
    }

    free(filename);

    // optional: pre-size the new file to the specified filesize...

    if (send_str(sockfd, "OK") < 0)
        return -1;

    char buffer[BUFFER_SIZE];
    int b;
    uint64_t total = 0;

    while (filesize > 0)
    {
        b = (filesize > BUFFER_SIZE) ? BUFFER_SIZE : (int) filesize;

        res = recv_all(sockfd, buffer, b);
        if (res <= 0)
        {
            fclose(fp);
            return -1;
        }

        if (fwrite(buffer, b, 1, fp) < 1)
        {
            perror("Could not write to file");
            fclose(fp);
            send_str(sockfd, "ERROR");
            return -1;
        }

        total += b;
        filesize -= b;
    }

    fclose(fp);
    printf("Received bytes: %lu\n", total);

    if (send_str(sockfd, "OK") < 0)
        return -1;

    return 1;
}

int main()
{
    int port = 6666;
    int server_fd, client_fd, read;
    struct sockaddr_in server, client;
    char filename[BUFFER_SIZE], *cmd;
    char remote_ip[16];
    int remote_port, res = 0;

    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0)
    {
        perror("Could not create socket");
        return 1;
    }

    int optval = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));

    memset(&server, '\0', sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(server_fd, (struct sockaddr *) &server, sizeof(server)) < 0)
    {
        perror("Could not bind socket");
        close(server_fd);
        return 1;
    }

    if (listen(server_fd, 1) < 0)
    {
        perror("Could not listen on socket");
        close(server_fd);
        return 1;
    }

    printf("Server TCP is listening on port %d ... \n", port);

    socklen_t client_len = sizeof(client);
    client_fd = accept(server_fd, (struct sockaddr *) &client, &client_len);

    if (client_fd < 0)
    {
        perror("Could not establish new connection");
        close(server_fd);
        return 1;
    }

    remote_port = ntohs(client.sin_port);
    inet_ntop(AF_INET, &client.sin_addr, remote_ip, sizeof(remote_ip));

    printf("Client IP address: %s, port %d\n", remote_ip, remote_port);

    while (recv_str(client_fd, &cmd) > 0)
    {
        printf("-------FROM CLIENT: %s-------\n", cmd);

        if (strcmp(cmd, "SENDFILE_TXT") == 0)
        {
            if (recv_txt_file(client_fd) < 0)
                break;
        }
        else
        {
            if (send_str(client_fd, cmd) < 0)
            {
                free(cmd);
                break;
            }
        }

        free(cmd);
    }

    close(client_fd);
    close(server_fd);

    return 0;
}

client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <stdint.h>

#define BUFFER_SIZE 1024

socklen_t hostname_to_ip_port(char *hostname, int port, struct sockaddr_storage *addr)
{
    int sockfd;
    struct addrinfo hints, *servinfo;
    int rv;

    char service[20];
    sprintf(service, "%d", port);

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    if ((rv = getaddrinfo(hostname, service, &hints, &servinfo)) != 0)
    {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 0;
    }

    socklen_t addrlen = servinfo->ai_addrlen;
    memcpy(addr, servinfo->ai_addr, addrlen);

    freeaddrinfo(servinfo);

    return addrlen;
}

int send_all(int sockfd, const void *buf, size_t len)
{
    ssize_t n;
    const char *pbuf = (const char *) buf;

    while (len > 0)
    {
        n = send(sockfd, pbuf, len, 0);
        if (n < 0)
        {
            perror("Server write failed");
            return n;
        }
        pbuf += n;
        len -= n;
    }

    return 0;
}

int send_uint32(int sockfd, uint32_t value)
{
    value = htonl(value);
    return send_all(sockfd, &value, sizeof(value));
}

int send_uint64(int sockfd, uint64_t value)
{
    value = htonll(value); // <-- use any implementation of your choosing...
    return send_all(sockfd, &value, sizeof(value));
}

int send_str(int sockfd, const char *s)
{
    uint32_t len = strlen(s);
    int res = send_uint32(sockfd, len);
    if (res == 0)
        res = send_all(sockfd, s, len);
    return res;
}

int recv_all(int sockfd, void *buf, int len)
{
    ssize_t n;
    char *pbuf = (char*) buf;

    while (len > 0)
    {
        n = recv(sockfd, pbuf, len, 0);
        if (n <= 0)
        {
            if (n < 0)
                perror("Server read failed");
            else
                printf("Server disconnected\n");
            return n;
        }
        pbuf += n;
        len -= n;
    }

    return 1;
}

int recv_uint32(int sockfd, uint32_t *value)
{
    int res = recv_all(sockfd, value, sizeof(*value));
    if (res > 0)
        *value = ntohl(*value);
    return res;
}

int recv_str(int sockfd, char **str)
{
    uint32_t len;

    int res = recv_uint32(sockfd, &len);
    if (res <= 0)
        return res;

    *str = (char*) malloc(len + 1);
    if (*str == NULL)
    {
        perror("Could not allocate memory");
        return -1;
    }

    res = recv_all(sockfd, *str, len);
    if (res <= 0)
        free(*str);
    else
        (*str)[len] = '\0';

    return res;
}

int send_txt_file(int sockfd, const char *filename)
{
    char *resp;
    int res;
    long int filesize;
    char buffer[BUFFER_SIZE];
    int b;

    FILE* fp = fopen(filename, "rb");
    if (fp == NULL)
    {
        printf("Could not open file!\n");
        return 0;
    }

    fseek(fp, 0L, SEEK_END);
    filesize = ftell(fp);
    fseek(fp, 0L, SEEK_SET);

    if (filesize < 0)
    {
        fclose(fp);
        return 0;
    }

    if (send_str(sockfd, "SENDFILE_TXT") < 0)
    {
        fclose(fp);
        return -1;
    }

    if (send_str(sockfd, filename) < 0)
    {
        fclose(fp);
        return -1;
    }

    if (send_uint64(sockfd, filesize) < 0)
    {
        fclose(fp);
        return -1;
    }

    res = recv_str(sockfd, &resp);
    if (res <= 0)
        return -1;

    printf("-------FROM SERVER: %s-------\n", resp);

    if (strcmp(resp, "OK") != 0)
    {
        free(resp);
        fclose(fp);
        return 0;
    }

    free(resp);

    while (filesize > 0)
    {
        b = (filesize > BUFFER_SIZE) ? BUFFER_SIZE : (int) filesize;

        b = fread(buffer, 1, b, fp);
        if (b < 1)
        {
            fclose(fp);
            return -1;
        }

        if (send_all(sockfd, buffer, b) < 0)
        {
            fclose(fp);
            return -1;
        }

        filesize -= b;
    }

    fclose(fp);

    res = recv_str(sockfd, &resp);
    if (res <= 0)
        return -1;

    printf("-------FROM SERVER: %s-------\n", resp);

    free(resp);

    return 0;
}

int prompt(const char *text, char **input)
{
    *input = NULL;
    size_t size = 0;

    printf("%s> ", text);

    ssize_t len = getline(input, &size, stdin);
    if (len < 0)
        return len;

    if ((*input)[len-1] == '\n')
    {
        --len;
        (*input)[len] = '\0';
    }

    return len;
}

int main()
{
    char *hostname = "127.0.0.1";
    int port = 6666;
    char *cmd, *resp, *fname;
    size_t size;
    ssize_t len;

    int sockfd, res;
    struct sockaddr_storage server_addr;
    socklen_t server_addr_len;

    server_addr_len = hostname_to_ip_port(hostname, port, &server_addr);
    if (server_addr_len == 0)
        return 1;

    sockfd = socket(server_addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
    if (sockfd < 0)
    {
        perror("Could not create socket");
        return 1;
    }

    if (connect(sockfd, (struct sockaddr *) &server_addr, server_addr_len) < 0)
    {
        perror("Could not connect socket");
        return 1;
    }

    while (prompt("", &cmd) >= 0)
    {
        if (strcmp(cmd, "SENDFILE_TXT") == 0)
        {
            if (prompt("Give filename", &fname) < 0)
                break;

            if (send_txt_file(sockfd, fname) < 0)
                break;

            free(fname);
        }
        else
        {
            if (send_str(sockfd, cmd) < 0)
            {
                free(cmd);
                close(sockfd);
                return 1;
            }

            if (recv_str(sockfd, &resp) <= 0)
                break;

            printf("FROM SERVER: %s\n", resp);
            free(resp);
        }

        free(cmd);
    }

    close(sockfd);

    return 0;
}

regarding:

int total = 0, b = 0;

and

while(recv_all(sockfd, buffer, len) != 1)
{
    total += b;
    fwrite(buffer, 1, b, fp);

the total and b never move from their initial value of 0. So 0 bytes are written to the output file.

Related