• 【文件传输】实现下载


    下载:

    如下图:

    1. 如果刚发完size,客户端不回复ok,直接发送数据,会出现粘包问题
    2. 如果想要确保客户端收到数据,可以每发送一个数据,客户端回复一个ok。
      请添加图片描述

    下载的过程:

    单文件传输:

    1. 客户端发送 get a.c 给服务器
    2. 服务器查看其目录中是否a.c文件
    3. 如果有,回复ok,并将a.c文件的大小发送给客户端。(用来提示客户端什么时候下载完),否则回复error (名字错误,没有找到等等错误)
    4. 客户端收到服务器的确认,并回复服务器ok。
    5. 服务器开始发送数据。(一次或多次)

    多文件传输:

    1. 客户端发送 get a.c b.c给服务器
    2. 服务器查看其目录中是否a.c b.c文件
    3. 如果有,回复ok。
    4. 客户端收到服务器的确认,创建2个链接,专门负责a.c 和b.c文件的传输,并回复服务器ok。(直到链接关闭,说明文件传输完了)
    5. 服务器开始发送数据。(一次或多次)

    lseek:获取文案描述符的偏移量(文件大小)
    服务器 thread.c

    void send_file(int c,char *filename)
    {
            if(filename == NULL)
            {
                    send(c,CMD_ERR,strlen(CMD_ERR),0);
                    return;
            }
           int fd = open(filename,O_RDONLY);
           if(fd == -1)
           {
                   send(c,FILE_ERR,strlen(FILE_ERR),0);
                   return;
           }
           //lseek,将文件的偏移量指针末尾
        int filesize = lseek(fd,0,SEEK_END);
        lseek(fd,0,SEEK_SET);
       //将文件偏移指针移动到文件开始
        char buff_size[64] = {0};
        sprintf(buff_size,"ok#%d",filesize);
        send(c,buff_size,strlen(buff_size),0);
       //发送文件大小
        memset(buff_size,0,64);
        int n = recv(c,buff_size,63,0);
        if ( n <= 0 )
        {
            return;
        }
        if ( strcmp(buff_size,"err") == 0 )
        {
            return;
        }
    
        char data[1024];
        int num = 0;
        //读取文件内容
        while( (num = read(fd,data,1024)) > 0 )
        {
            send(c,data,num,0);
        }
        close(fd);
        return;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    客户端:

    //cmd_buff : get a.c
    void recv_file(int c, char cmd_buff[], char* filename)
    {
      if(cmd_buff == NULL || filename == NULL)
      {
              return;
      }
      send(c,cmd_buff,strlen(cmd_buff),0);
    
      char buff[64] = {0};
      int  num = recv(c,buff,63,0);
     if(num <= 0)
     {
             printf("ser close or err\n");
             return;
     } 
     
     //ok#size  ,有数据就可以写数据
     int filesize = 0;
     sscanf(buff+3,"%d",&filesize);
     printf("文件:%s,大小:%d\n",filename,filesize);
     if ( filesize < 0 )
        {
            send(c,"err",3,0);
            return;
        }
    
        int fd = open(filename,O_CREAT|O_WRONLY,0600);
        if ( fd == -1 )
        {
            printf("创建文件失败\n");
            send(c,"err",3,0);
            return;
        }
    
        send(c,"ok",2,0);
        char data[1024];
        int curr_size = 0;
        while( 1 )
        {
            int n = recv(c,data,1024,0);
            if ( n <= 0 )
            {
                printf("down file err\n");
                break;
            }
    
            write(fd,data,n);
            curr_size += n;
            float f = curr_size * 100.0 / filesize;
            printf("当前下载:%.2f%%\r",f);
            fflush(stdout);
    
            if ( curr_size >= filesize )
            {
                break;
            }
        }
        close(fd);
        printf("\n");
        printf("文件下载完成\n");
        return ;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
  • 相关阅读:
    弘辽科技:拼多多上下架会不会影响到流量?时间如何安排?
    碳中和&专利创新专题:各省市县专利面板(原始文件)、低碳专利授权数等多指标数据
    池风水利用工具
    Linux系统tcp连接设置
    每日一题 213. 打家劫舍 II
    AFG EDI 解决方案
    8.StringTable(字符串常量池)
    CCNA-NAT协议(理论与实验练习)
    JS之函数的属性
    十、DPDK协议栈之ddos和epoll
  • 原文地址:https://blog.csdn.net/weixin_52958292/article/details/127851235