TFTP系统下载上传TXT文件(不带选项)

 

目录

数据包格式:

一、下载

步骤1:创建udp套接字

步骤2:组读请求(0,1,“a.txt”,0,"netascii",0),发送给服务器

步骤3:创建并打开本地文件

步骤4:循环接受数据buf

步骤5:关闭文件描述符,关闭套接字

 二、上传

步骤1:创建udp套接字

步骤2:组写请求(0,2,“a.txt”,0,"netascii",0),发送给服务器

步骤3:打开本地文件a.txt

步骤4:循环接受数据buf

步骤5:关闭文件描述符,关闭套接字


数据包格式:

TFTP系统下载上传TXT文件(不带选项)

一、下载

步骤1:创建udp套接字

    int scokfd=socket(AF_INET,SOCK_DGRAM,0);
    if(scokfd<0)
    {
        printf("套接字创建失败\n");
        return -1;
    }
    else
        printf("套接字创建成功\n");

步骤2:组读请求(0,1,“a.txt”,0,"netascii",0),发送给服务器

    struct sockaddr_in ser_ddr;
    bzero(&ser_ddr,sizeof(ser_ddr));
    ser_ddr.sin_family=AF_INET;
    ser_ddr.sin_port=htons(69);
    inet_pton(AF_INET,"10.36.145.87",(void*)&ser_ddr.sin_addr);
    char buf[64]="";
    int buf_len=sprintf(buf,"%c%c%s%c%s%c",0,1,"a.txt",0,"netascii",0);
    sendto(scokfd,buf,buf_len,0,(struct sockaddr*)&ser_ddr,sizeof(ser_ddr));

步骤3:创建并打开本地文件

步骤4:循环接受数据buf

如果buf长度<516结束读取

查看buf[1]==3 "数据包" 写文件

回复 "ACK"  buf[1]==4

buf[1]==5  "ERROR" ;break;

    int fd =open("./a.txt",O_RDWR|O_CREAT,0666);
    if(fd<0)
    {
        perror(open);
        return -1;
    }
    char recv_buf[1024]="";
    int recv_len=0;
    struct sockaddr_in from_addr;
    socklen_t addrlen=sizeof(from_addr);
    while (1)
    {
        bzero(&from_addr,sizeof(from_addr));
        recv_len=recvfrom(scokfd,recv_buf,sizeof(recv_buf),0,(struct sockaddr*)&from_addr,&addrlen);
        if(recv_buf[1]==5)
        {
            printf("error:%s\n",recv_buf+4);
            break;
        }
        else if(recv_buf[1]==3)
        {
            write(fd,recv_buf+4,recv_len-4);
            //回复ACK
            recv_buf[1]=4;
            sendto(scokfd,recv_buf,4,0,(struct sockaddr *)&from_addr,sizeof(from_addr));
            if(recv_len<516)
                break;
        }
    }

步骤5:关闭文件描述符,关闭套接字

close(scokfd);

 close(fd);

 二、上传

步骤1:创建udp套接字

    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd<0){
		printf("创建失败\n");
		return 0;
		}
	else{
		printf("创建成功 %d\n",sockfd);
	}

步骤2:组写请求(0,2,“a.txt”,0,"netascii",0),发送给服务器

    struct sockaddr_in ser_addr;
	bzero(&ser_addr,sizeof(ser_addr));
	ser_addr.sin_family=AF_INET;
	ser_addr.sin_port=htons(69);
	inet_pton(AF_INET,"10.36.145.87",(void *)&ser_addr.sin_addr);
	char buf[64]="";
	int buf_len=sprintf(buf,"%c%c%s%c%s%c",0,2,"a.txt",0,"netascii",0);
	sendto(sockfd,buf,buf_len,0,(struct sockaddr *)&ser_addr,sizeof(ser_addr));

步骤3:打开本地文件a.txt

	int fd = open("./a.txt",O_RDWR);
	if(fd<0){
		perror("open");
		return 0;
		}

步骤4:循环接受数据buf

查看buf[0~1]==4------buf[2~3]=块编号;读文件,回复数据包seddbuf=(0,3,buf[2~3]+1,读文件512)

buf[1]==5;break;

	char rcv_buf[1024]="";
	int rcv_buf_len=0;
	unsigned short p_num=0;
	struct sockaddr_in from_addr;//服务器ip和服务器的临时端口
	socklen_t addrlen=sizeof(from_addr);
	while(1){
		bzero(&from_addr,sizeof(from_addr));
		recvfrom(sockfd, rcv_buf, sizeof(rcv_buf),0,(struct sockaddr*)&from_addr,&addrlen);
		if(rcv_buf[1]==5)//差错
		{
			printf("error:%s\n",rcv_buf+4);
			break;
		}
		else if(rcv_buf[1]==4)//ACK   
		{
			//读本地文件
			rcv_buf_len=	read(fd,rcv_buf+4,512);
			rcv_buf[1]=3;
			p_num=ntohs(*(unsigned short *)(rcv_buf+2));//取rcv_buf的3~4字节并保存到主机
			*(unsigned short *)(rcv_buf+2)=htons(p_num+1);
            
			//将ack包的编号+1,赋值给数据包0 4 0 x-------0 3 0 x+1 512byte
			printf("即将发送数据包编号:%d\n",p_num+1);
			sendto(sockfd,rcv_buf,rcv_buf_len+4,0,(struct sockaddr *)&from_addr,sizeof(from_addr));
			if(rcv_buf_len<512)
				break;
		}
		else;
	}

步骤5:关闭文件描述符,关闭套接字

close(sockfd);

close(fd);

上一篇:【Unity】12.4 通过网格分层选择行进路线


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