UDP based TFTP file transfer

TFTP file transfer based on UDP (client code)

Code:

#include <my_head.h>

#define SERVER_PORT 69
#define SERVER_IP "192.168.125.91"

int do_download(int client_fd, struct sockaddr_in server_in);
int do_updata(int client_fd, struct sockaddr_in server_in);

int main(int argc, const char *argv[])
{<!-- -->
    //Create a report socket
    int client_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (client_fd < 0)
    {<!-- -->
        ERR_MSG("socket");
        return -1;
    }
    printf("Socket created successfully client_fd = %d\
", client_fd);

    //Allow ports to be reused quickly
    int reuse = 1;
    if (setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, & amp;reuse, sizeof(reuse)) < 0)
    {<!-- -->
        ERR_MSG("setsockopt");
        return -1;
    }
    printf("Allow port fast reuse successfully\
");

    // Bind client information. Binding is not required. It is recommended not to bind.
    // If not bound, the operating system will automatically assign a port number

    //Specify server information
    struct sockaddr_in server_addr; // Information used to bind this host
    server_addr.sin_family = AF_INET; // AF_INET is required
                                                        // Because the report socket was created earlier using IPv4
    server_addr.sin_port = htons(SERVER_PORT); //Specify port number
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); // Bind local IP

    char choose = 0;
    while (1)
    {<!-- -->
        printf("-------------------Menu------------------\
");
        printf("-----------------1. Download------------------\
");
        printf("-----------------2. Upload------------------\
");
        printf("-----------------3. Exit------------------\
");
        printf("---------------------------------------------\
") ;
        printf("Please enter: ");
        choose = getchar();
        while (getchar() != '\
')
            ;

        switch (choose)
        {<!-- -->
        case '1':
            //  download
            do_download(client_fd, server_addr);
            break;
        case '2':
            // Upload
            do_updata(client_fd, server_addr);
            break;
        case '3':
            //  quit
            goto END;
            break;
        default:
            printf("Wrong selection, please re-enter\
");
            break;
        }
    }
END:
    //Close socket
    close(client_fd);
    return 0;
}

int do_download(int client_fd, struct sockaddr_in server_in)
{<!-- -->
    /*
     *ACK*/
    unsigned short ACK[2] = {<!-- -->0};
    /*
     * file name */
    char name[32];
    printf("Please enter the file name you want to download: ");
    scanf("%s", name);
    while (getchar() != 10)
        ;

    /*
     * Combine a download protocol package */
    char buff[516];
    // opcode
    unsigned short *opcode = (unsigned short *)buff;
    *opcode = htons(1);
    //  file name
    char *p2 = (char *)(opcode + 1);
    strcpy(p2, name);
    //  model
    char *mode = p2 + strlen(p2) + 1;
    strcpy(mode, "octet");

    /*
     * Calculate the actual length of the protocol packet */
    size_t size = 2 + strlen(p2) + 1 + strlen(mode) + 1;

    /*
     * Send the download protocol package to the server */
    if (sendto(client_fd, buff, size, 0, (struct sockaddr *) & amp;server_in, sizeof(server_in)) < 0)
    {<!-- -->
        ERR_MSG("sendto");
        return -1;
    }
    printf("Download protocol sent successfully\
");

    /*
     * Send and receive data */
    ssize_t res = 0;
    socklen_t server_in_len = sizeof(server_in);

    /*
     * File to store data packets */
    umask(0);
    int fd_w = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0664);

    while (1)
    {<!-- -->
        /*
         * Receive data packet */
        res = recvfrom(client_fd, buff, sizeof(buff), 0, (struct sockaddr *) & amp;server_in, & amp;server_in_len);
        if (res < 0)
        {<!-- -->
            ERR_MSG("recvfrom");
            return -1;
        }

        // store data packet
        char *data = buff + 4;
        if (write(fd_w, data, res - 4) < 0)
        {<!-- -->
            ERR_MSG("write");
            return -1;
        }

        // Assemble the ACK packet
        ACK[0] = htons(4);
        ACK[1] = *(((unsigned short *)buff) + 1);
        //Send ACK packet
        if (sendto(client_fd, ACK, sizeof(ACK), 0, (struct sockaddr *) & amp;server_in, sizeof(server_in)) < 0)
        {<!-- -->
            ERR_MSG("sendto");
            return -1;
        }
        // printf("ACK sent successfully\
");
        // Determine whether the data is less than 512Byte. If it is less than 512Byte, end the reception.
        if ((res - 4) < 512)
        {<!-- -->
            printf("Download completed\
");
            break;
        }
    }
    close(fd_w);
    return 0;
}

int do_updata(int client_fd, struct sockaddr_in server_in)
{<!-- -->
    struct sockaddr_in new_in;
    // new_in.sin_family = AF_INET;
    socklen_t new_in_len = sizeof(new_in);

    socklen_t server_in_len = sizeof(server_in);

    // block number
    unsigned short block_num = 1;
    //  file name
    char name[32];
    printf("Please enter the file name you want to upload: ");
    scanf("%s", name);
    while (getchar() != 10)
        ;

    /*
     * open a file */
    int fd_r = open(name, O_RDONLY);

    /*
     * Combine a download protocol package */
    char buff[516];
    // opcode
    unsigned short *opcode = (unsigned short *)buff;
    *opcode = htons(2);
    //  file name
    char *p2 = (char *)(opcode + 1);
    strcpy(p2, name);
    //  model
    char *mode = p2 + strlen(p2) + 1;
    strcpy(mode, "octet");

    /*
     * Calculate the actual length of the protocol packet */
    size_t size = 2 + strlen(p2) + 1 + strlen(mode) + 1;

    /*
     * Send the upload protocol package to the server */
    if (sendto(client_fd, buff, size, 0, (struct sockaddr *) & amp;server_in, sizeof(server_in)) < 0)
    {<!-- -->
        ERR_MSG("sendto");
        return -1;
    }
    printf("Download protocol sent successfully\
");

    /*
     * Receive protocol response */
    if (recvfrom(client_fd, buff, sizeof(buff), 0, (struct sockaddr *) & amp;new_in, & amp;new_in_len) < 0)
    {<!-- -->
        ERR_MSG("recvfrom");
        return -1;
    }
    printf("Protocol response operation code: %u\
", ntohs(*((unsigned short *)buff)));
    printf("Protocol response block number: %u\
", ntohs(*((unsigned short *)buff + 1)));

    //Send data and receive ACK
    ssize_t res = -1; // Return value of reading file
    ssize_t recv_res = 0; //Return value of receiving ACK

    /*
     *ACK*/
    // unsigned int ACK = 0;

    while (1)
    {<!-- -->
        bzero(buff, sizeof(buff));

        /*
         * Group data packet */
        // opcode
        unsigned short *opcode = (unsigned short *)buff;
        *opcode = htons(3);
        // block number
        unsigned short *b_num = opcode + 1;
        *b_num = htons(block_num);
        /*
         * data */
        // read file
        res = read(fd_r, buff + 4, 512);
        if (res < 0)
        {<!-- -->
            ERR_MSG("read");
            return -1;
        }
        else if (0 == res)
        {<!-- -->
            printf("Reading file completed\
");
        }

        printf("sizeof(buff) = %ld\
", sizeof(buff));

        server_in_len = sizeof(server_in);
        //Send packet
        if (sendto(client_fd, buff, sizeof(buff), 0, (struct sockaddr *) & amp;new_in, new_in_len) < 0)
        {<!-- -->
            ERR_MSG("sendto");
            return -1;
        }
        printf("Send data packet\
");

        /*
         * Receive response ACK */
        recv_res = recvfrom(client_fd, buff, sizeof(buff), 0, (struct sockaddr *) & amp;new_in, & amp;new_in_len);
        if (recv_res < 0)
        {<!-- -->
            ERR_MSG("recvfrom");
            return -1;
        }

        printf("Operation code ---: %u\
", ntohs(*((unsigned short *)buff)));
        printf("Block number ---: %u\
", ntohs(*((unsigned short *)buff + 1)));

        if (5 == ntohs(*((unsigned short *)buff)))
        {<!-- -->
            printf("__%d__ ACK opcode error\
", __LINE__);
            printf("errro message : %s\
", buff + 4);
            return -1;
        }
        // Determine whether the packet is lost ---- Determine whether the previous data packet needs to be resent.
        if (block_num - (ntohs(*((unsigned short *)buff + 1))))
        {<!-- -->
            printf("__%d__ packet loss\
", __LINE__);
            lseek(fd_r, -(block_num - ntohs(*((unsigned short *)buff + 1))), SEEK_CUR);
            printf("Offset forward\
");
            continue;
        }

        if (0 == res)
        {<!-- -->
            printf("Upload completed\
");
            break;
        }

        block_num + + ;
        printf("Block number------%u\
", block_num);
    }
    close(fd_r);
    return 0;
}