ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

125_TFTP协议编程_基于UDP协议_客户端(虚拟机)不带选项,发送组写请求,向服务器(tftpd32所在文件夹)写文件案例【使用基础函数、✳3.2组写的介绍+伪代码实现✳】

2021-09-25 14:58:42  阅读:129  来源: 互联网

标签:addr sock 虚拟机 fd 3.2 服务器 组写 rec buf


图片:

在这里插入图片描述

#if 1 //-----------组【写】请求-------------//

int main()
{

    //创建套接字
    int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock_fd < 0)
    {
        perror("error");
    }
    else
    {
        printf("创建成功! %d\n", sock_fd);//文件描述符0 1 2已被使用,最小就是3开始
    }

    //【虚拟机】给【服务器Tptpd32】发送【上传】a.txt的请求
    //服务器就是我们的Tptpd32工具
    //他的IP是我们的本机IP:10.36.145.91
    //端口固定69
    //给【特定端口、IP】发送请求
    struct sockaddr_in ser_addr;
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_port = htons(69); //指定端口  69,虚拟机下都是小端,转成window下识别的大端数据
    inet_pton(AF_INET, "10.36.145.91", (void *)&ser_addr.sin_addr);//指定IP,点分十进制,转成32位无符号整数,window下识别的IP数据

    //组【写】请求
    char buf[64] = "";
    int buf_len = sprintf(buf, "%c%c%s%c%s%c", 0, 2,"a.txt", 0, "netascii", 0);
    //把组写请求,发送到服务器上
    //等待服务器回应
    sendto(sock_fd, buf, buf_len, 0, (struct sockaddr *)&ser_addr, sizeof(ser_addr));

    //打开本地文件
    int fd = open("a.txt", O_RDWR);
    if(fd < 0)
    {
        perror("error");
        return 0;
    }


    //接收数据包
    char rec_buf[1024] = "";//不能小于516
    int rec_buf_len = 0;
    unsigned short p_num = 0;//short类型占两个字节,计算【块编号】


    //存储服务器的信息-----交流的时候服务器的端口,一直是【动态】的
    struct sockaddr_in from_addr;
    socklen_t addrlen = sizeof(from_addr);

    while(1)
    {        
        bzero(&from_addr, sizeof(from_addr));

        //上面发送了写信息
        //会从服务器接收到ACK的包信息:[0 4 0 0],存进rec_buf数组
        recvfrom(sock_fd, rec_buf, sizeof(rec_buf), 0,\
                            (struct  sockaddr*)&from_addr, &addrlen);

        
        //根据操作码的第二位的标志位判定
        //接收出差错了
        if(rec_buf[1] == 5)
        {
            printf("error = %s\n", rec_buf + 4);
            break;
        }
        else if(rec_buf[1] == 4)
        {//先收到一次ACK[0 4 0 0]---->然后发送数据包,数据包构成:[0 3 0 1 512byte]
         //[0 3 0 1]:操作位+块编号
         //512byte:一次上传服务器内容大小

            //跳过[0 4 0 0]前四位【操作码、块编号】
            //把文件内容读到数组中,读512字节数据
            rec_buf_len = read(fd, rec_buf + 4, 512);

            //在网络层通过IP进行信息交互
            //数据格式需要改变!!!



            //ACK收到,开始发送数据包
            rec_buf[1] = 3;

            //接收到一个,需要对块编号,进行++了
            //unsigned short * :拿到编号位short两个字节的[0 0]的首地址,
            //取地址,把计算后的值 0 赋值给p_num
            //先在客户端【虚拟机】上,对数据包的块编号+1,
            //且需要对之前从服务器接收到的大端【块编号】,进行小端处理才行   
            p_num = ntohs( *(unsigned short *)(rec_buf + 2));

            //p_num + 1  得到--->1
            //再计算完成后
            //转成服务器适用的【大端】数据
            //1 变成 [0 1],第一位补0,完成块编号的++操作
            *(unsigned short *)(rec_buf + 2) = htons(p_num + 1);
            printf("即将发送数据包编号:%d\n",p_num+1);

            //发送的数据,去除【操作码、块编号】的四个字节
            sendto(sock_fd, rec_buf, rec_buf_len + 4, 0, (struct  sockaddr*)&from_addr,sizeof(from_addr));
            if(rec_buf_len < 512)
            {
                printf("文件读取完\n");
                break;
            }
        }

   
    }


    close(sock_fd);
    close(fd);




    return 0;
}

#endif

标签:addr,sock,虚拟机,fd,3.2,服务器,组写,rec,buf
来源: https://blog.csdn.net/HanLongXia/article/details/120471426

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有