用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字

芙蓉妹妹    -  云代码空间

——

利用UDP完成文件传输

2018-11-05|1257阅||

摘要:利用循环面向连接的模型完成固定文件的传输(考虑服务器地址、端口号的设定方式);由固定文件扩展成手动输入或选择文件;

一、服务端(server.c)

# include <stdio.h>

# include <sys/types.h>

# include <sys/socket.h>

# include <unistd.h>

# include <netinet/in.h>

# include <arpa/inet.h>

# include <stdlib.h>

# include <errno.h>

# include <fcntl.h>

# include <netdb.h>

# include <stdarg.h>

# include <string.h>

# define PORT 8888

# define BUFFER_SIZE 1024

# define FILE_NAME_MAX_SIZE 512

typedef struct

{

    int id;/*数据包的编号*/

    int buf_size;/*数据包的大小*/

} Packinfo;

struct Sendpack

{

    Packinfo head;/*数据识别信息*/

    char buf[BUFFER_SIZE];/*用于存放文件数据*/

} data;

int main(void)

{

    int send_id = 0;

    int receive_id = 0;

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    if(-1 == sockfd)

    {

        perror("socket failed");

        return -1;

    }

    struct sockaddr_in server_addr;

    server_addr.sin_family = AF_INET;

    server_addr.sin_port = htons(PORT);

    inet_aton("192.168.91.128", &server_addr.sin_addr);

    int ret = bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));

    if(-1 == ret)

    {

        perror("bind failed");

        return -1;

    }

    while(1)

    {

        struct sockaddr_in client_addr;

        socklen_t client_addr_len = sizeof(client_addr);

        char buffer[FILE_NAME_MAX_SIZE] = {0};

        if(-1 == recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&client_addr, &client_addr_len))

        {

            perror("recvfrom failed");

            return -1;

        }

        printf("客户端地址为:%s  %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        char file_name[FILE_NAME_MAX_SIZE + 1] = {0};

        strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));

        printf("服务器处理过后的文件名称为:%s\n", file_name);

        int fd = open(file_name, O_RDONLY);

        if(-1 == fd)

        {

            perror("open failed");

            return -1;

        }

        else

        {

            printf("打开文件成功!\n");

            int len = 0;

            Packinfo pack_info;//定义数据包头结构体变量

            while(1)

            {

                if(receive_id == send_id)//此时都为0

                {

                    ++send_id;

                    len = read(fd, data.buf, sizeof(data.buf));

                    printf("len = %d\n", len);

                    if(len > 0)

                    {

                        printf("%d次读取到的内容为:%s\n", send_id, data.buf);

                        data.head.id = send_id;

                        data.head.buf_size = len;

                        if(sendto(sockfd, &data, sizeof(data), 0, (struct sockaddr*)&client_addr, sizeof(client_addr)) < 0)

                        {

                            perror("sendto failed");

                            return -1;;

                        }

                        printf("向客户端发送数据成功\n");

                        if(recvfrom(sockfd, &pack_info, sizeof(pack_info), 0, (struct sockaddr*)&client_addr, &client_addr_len)<0)

                        {

                            perror("recvfrom failed");

                            return -1;

                        }

                        printf("从客户端读到的内容为:id = %d buf_size = %d\n", pack_info.id, pack_info.buf_size);

                        receive_id = pack_info.id;

                    }

                    else if(len < 0)

                    {

                        perror("read failed");

                        return -1;

                    }

                    else

                        break;

                }

                else/*如果receive_id 不等于 send_id 即客户端接收到的数据和服务器发送的数据不一致的话就重新发送*/

                {

                    if(sendto(sockfd, &data, sizeof(data), 0, (struct sockaddr*)&client_addr, client_addr_len<0))

                    {

                        perror("sendto failed");

                        return -1;

                    }

                    printf("重新向客户端发送数据成功\n");

                    /*重新接收客户端反馈信息*/

                    if(recvfrom(sockfd, &pack_info, sizeof(pack_info), 0, (struct sockaddr*)&client_addr, &client_addr_len)<0)

                    {

                        perror("recvfrom failed");

                        return -1;

                    }

                    printf("从客户端读到的内容为:id = %d buf_size = %d\n", pack_info.id, pack_info.buf_size);

                    printf("-----------------------------------\n");

                    receive_id = pack_info.id;

                }

            }

            /*关闭文件*/

            close(fd);

            printf("File:%s Transfer Successful!\n", file_name);

            break;

        }

    }

    /*关闭套接字*/

    close(sockfd);

    return 0;

}

二、服务端(client.c)

# include <stdio.h>

# include <stdlib.h>

# include <string.h>

# include <fcntl.h>

# include <unistd.h>

# include <sys/types.h>

# include <sys/socket.h>

# include <netinet/in.h>

# include <arpa/inet.h>

# include <errno.h>

# define PORT 8888

# define BUFFER_SIZE 1024

# define FILE_NAME_MAX_SIZE 512

typedef struct

{

    int id;

    int buf_size;

} Packinfo;

struct package

{

    Packinfo head;

    char buf[BUFFER_SIZE];

} data;

int main(void)

{

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    if(-1 == sockfd)

    {

        perror("socket failed");

        exit(-1);

    }

    struct sockaddr_in server_addr;

    server_addr.sin_family = AF_INET;

    server_addr.sin_port = htons(PORT);

    inet_aton("192.168.91.128", &server_addr.sin_addr);

    socklen_t server_addr_len = sizeof(server_addr);

    char file_name[FILE_NAME_MAX_SIZE + 1] = {0};

    printf("请输入文件名称:");

    scanf("%s",file_name);//get filepath

    char str[FILE_NAME_MAX_SIZE] = {0};

    strncpy(str, file_name, strlen(file_name)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(file_name));

    printf("--------------------------------------------\n");

    printf("客户端处理过后的文件名称为:%s\n", str);

    int fd = open(file_name, O_RDWR|O_CREAT|O_TRUNC, 0664);

    if(fd < 0)

    {

        perror("open failed");

        exit(-1);

    }

    printf("客户端创建文件成功\n");

    if(sendto(sockfd, str, sizeof(file_name), 0, (struct sockaddr*)&server_addr, server_addr_len)<0)

    {

        perror("sendto failed");

        exit(-1);

    }

    printf("向服务器发送文件名称成功\n");

    int id = 1;

    int len = 0;

    Packinfo pack_info;

    while(1)

    {

        printf("客户端等待接收服务器信息\n");

        len = recvfrom(sockfd, &data, sizeof(data), 0, (struct sockaddr*)&server_addr, &server_addr_len);

        printf("len = %d\n", len);

        if(len > 0)

        {

            printf("从服务器接收到的数据为:%s\n", data.buf);

            if(data.head.id == id)//如果数据的编号相等

            {

                pack_info.id = data.head.id;

                pack_info.buf_size = data.head.buf_size;

                ++id;

                if(sendto(sockfd, (char*)&pack_info, sizeof(Packinfo), 0, (struct sockaddr*)&server_addr, server_addr_len)<0)

                {

                    perror("pick_info sendto failed");

                    break;

                }

                printf("向服务器发送确认信息成功\n");

                if(write(fd, data.buf, sizeof(data.buf))<data.head.buf_size)

                {

                    perror("write failed");

                    return -1;

                }

                printf("向文件中写入的数据为:%s\n", data.buf);

                memset(data.buf, 0, sizeof(data.buf));

            }

            else if(data.head.id != id)

            {

                pack_info.id = data.head.id;

                pack_info.buf_size = data.head.buf_size;

                if(sendto(sockfd, (char*)&pack_info, sizeof(pack_info), 0, (struct sockaddr*)&server_addr, server_addr_len)<0)

                {

                    perror("重发数据包sendto failed");

                    return -1;;

                }

                printf("重新向服务器发送数据成功\n");

            }

        }

        else if(len < 0)

        {

            perror("recvfrom failed");

            return -1;

        }

        else

            break;

    }

    printf("Receive File :\t%s From Server IP Successful!\n", file_name);

    close(fd);

    close(sockfd);

    return 0;

}
三、实验截屏
服务端:

客户端:

实验前无test1.txt文件:

实验后出现test1.txt文件:

顶 2踩 2收藏
文章评论
    发表评论

    个人资料

    • 昵称: 芙蓉妹妹
    • 等级: 资深程序员
    • 积分: 1710
    • 代码: 104 个
    • 文章: 25 篇
    • 随想: 0 条
    • 访问: 32 次
    • 关注

    标签

    最新提问

      站长推荐