使用TFTP协议下载文件

2023-05-16

TFTP协议

最初用于引导无盘系统,被设计用来传输小文件

  1. TFTP基于UDP协议。
  2. TFTP的编程思想 和 UDP一样
  3. TFTP:简单文件传送协

特点:

  1. 基于UDP协议实现
  2. 不进行用户有效性认证

数据传输模式:

  1. octet:二进制模式
  2. netascii:文本模式
  3. mail:已经不再支持

TFTP通信过程总结(无选项)

在这里插入图片描述

  1. 服务器在69号端口等待客户端的请求
  2. 服务器若批准此请求,则使用临时端口与客户端进行通信
  3. 每个数据包的编号都有变化(从1开始)、逐次递增
  4. 每个数据包都要得到ACK的确认如果出现超时,则需要重新发送最后的包(数据或ACK)
  5. 数据的长度以512Byte传输
    小于512Byte的数据意味着传输结束

TFTP协议报文分析

前两个字节为操作码
在这里插入图片描述
注意:

  1. 以上的0代表的是’\0’
  2. 不同的差错码对应不同的错误信息

在这里插入图片描述

TFTP带选项

在这里插入图片描述
tsize选项

  • 当读操作时,tsize选项的参数必须为“0”,服务器会返回待读取的文件的大小
  • 当写操作时,tsize选项参数应为待写入文件的大小,服务器会回显该选项

blksize选项

  • 修改传输文件时使用的数据块的大小(范围:8~65464)

timeout选项

  • 修改默认的数据传输超时时间(单位:秒)

代码示例

此处为 客服端,服务器端可以配合此软件测试。

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <cstdio>
#include <cstring>
#include <unistd.h>

using namespace std;

int main(int argc,char *argv[])
{
    if(argc != 2){
        perror("参数过少");
        exit(1);
    }
    int sockfd;
    if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) == -1){
        perror("socket err");
        exit(1);
    }
    char cmd[128] = "";
    int len = sprintf(cmd,"%c%c%s%c%s%c",0x00,0x01,argv[1],0,"octet",0);

    struct sockaddr_in servAddr;
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = inet_addr("192.168.217.1");
    servAddr.sin_port = htons(69);
    socklen_t servLen = sizeof(servAddr);
    sendto(sockfd,cmd,len,0,(struct sockaddr*)&servAddr,servLen);
    int fd = open("/home/hehe.mp4",O_CREAT|O_RDWR|O_TRUNC,S_IRWXU);
    if(fd == -1){
        perror("open error");
        exit(1);
    }
    unsigned char buf[1024] = "";
    memset(buf,0,sizeof (buf));
    struct sockaddr_in clieAddr;
    socklen_t clieLen = sizeof(clieAddr);
    unsigned short num = 1;
    while (1) {
        int recvLen = recvfrom(sockfd,buf,sizeof (buf),0,(struct sockaddr*)&clieAddr,&clieLen);
        //如果收到的是数据包的操作码,那么将数据写入到文件中
        if(buf[1] == 0x03){
        	//假如自己回的ACK包丢失了,服务器会重新传这个包,所以需要对包编号加判断,如果是正确的包才写入文件,防止文件混乱
            if(num == ntohs(*(unsigned short*)(buf+2))){
                //将数据写入到本地文件"./home/test.txt"中,四个字节的包头跳过
                write(fd,buf+4,recvLen-4);
                ++num;
                cout << ntohs(*(unsigned short*)(buf+2)) << endl;
            }
            //回复服务器ACK包
            buf[1] = 0x04;
            sendto(sockfd,buf,4,0,(struct sockaddr*)&clieAddr,clieLen);
            //如果接受的文件大小小于512字节,说明是最后一个包了,已经传输完毕,跳出循环
            if(recvLen < 512){
                break;
            }
        }
    }
    close(fd);
    close(sockfd);
    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用TFTP协议下载文件 的相关文章

随机推荐

  • C语言对另一种企业单向链表的初始化、插入、删除、销毁等操作

    链表模型 只将前四个字节用来作为指针域 xff0c 并且只对指针域进行操作即可 xff0c 并不会对数据进行操作 链表代码实现 span class token macro property span class token directi
  • C语言模拟顺序栈的出栈、入栈、返回栈顶元素等操作

    使用数组模拟顺序栈 栈底为数组的首地址 xff0c 栈顶为数组的尾地址 xff0c 因为数组中尾插不需要一个一个移动数据 xff0c 相比头插效率更高 span class token macro property span class t
  • Linux系统编程之readdir()函数判断目录是否为空的问题

    由于Linux目录中总是存在 两个隐藏目录 xff0c 所以在用readdir 函数判断是否为空时 xff0c 得到的结果总是目录不为空 但是现实中对于如果目录中没有自己的文件就应该被判为空 xff0c 所以在多次测试之后得到下面这段判断目
  • Linux系统编程之wait()函数回收子进程

    一次调用wait或waitpid函数只能回收一个子进程 xff0c 当有多个子进程时应使用循环 如果想回收指定进程 xff0c 使用waitpid函数 函数原型 pid t wait int status 返回值 成功 xff1a 清理掉的
  • 神秘的程序员

    神秘的程序员漫画集
  • 进程间通信方法一:管道:pipe()、fifo

    管道的实现原理是内核使用循环队列机制 xff0c 借助内核缓冲区 xff08 4K xff09 实现 管道的局限性 xff1a 由于管道采用半双工的通信方式 xff0c 所以数据只能在一个方向上流动 xff0c 要不读要不写 xff08 读
  • Linux系统编程之进程间通信二:内存映射区

    1 内存映射区 1 1mmap函数 函数功能 创建内存映射将磁盘文件的数据映射到内存中 xff0c 通过修改内存就能修改磁盘文件 函数原型 length xff1a 大小为4K的倍数 xff0c 且不能为0 一般文件多大 xff0c 映射区
  • Linux系统编程之多线程并发服务器简单实现

    服务端 当有客户端连接服务端后 xff0c 客户端发送小写字母 xff0c 服务端转换为大写字母后发送给客户端 span class token macro property span class token directive keywo
  • vim中配置C/C++环境

    在vim中配置C C 43 43 环境 xff1a 详见资源下载地址 xff1a VIM配置C C 43 43 配置开发环境 包括代码函数自动补全 括号自动补全与详细的配置步骤等 xff0c 基本是一个完整的代码编辑器 配置完后如果使用Xs
  • Linux系统调用函数read()返回值判断

    函数原型 read int fd void buf size t count 函数说明 将从文件描述符fd对应的文件中读到的数据存在buf缓冲区中 xff0c 每次读count字节 xff0c 同时文件指针会随着移动 函数返回值 当返回值大
  • Linux系统编程之多进程并发服务器简单实现

    服务端 span class token macro property span class token directive keyword include span span class token string lt stdio h g
  • 多路IO转接服务器实现方法一:select()函数

    采用多进程与多线程的方法来实现并发服务器时 xff0c 监听的工作由server应用程序自身通过accept函数不断去监听 当客户端连接较多时 xff0c 这种方法会大大降低程序执行效率 xff0c 消耗CPU资源 xff08 CPU需要在
  • 多路IO转接服务器实现方法二:poll()函数

    相较于多路IO转接服务器实现方法一 xff1a select 函数 xff0c 使用poll 函数的优点有 文件描述符的上限可以突破1024select 函数监听集合与返回的满足监听条件的集合为一个集合 xff0c 而poll函数将监听集合
  • 多路IO转接服务器实现方法三:epoll()函数

    epoll是Linux下多路复用接口select poll的增强版本 它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率 xff0c 因为它会复用文件描述符集合来传递结果而不用每次等待时间之前都必须重新准备要被监听的文件
  • epoll函数之边缘触发、水平触发、非阻塞IO模式

    1 边沿触发与水平触发 这两个实际是由模拟电路上的高低电频来的 xff0c 低电压 0 到高电压 1 为上升沿 xff0c 高电压 1 到低电压 0 为下降沿 xff0c 高电压 1 到高电压 1 为水平沿 水平沿对应水平触发 xff0c
  • linux getty命令参数及用法详解--linux开启及设置终端命令

    getty get teletypewriter 功能说明 xff1a 是Unix类操作系统启动时必须的三个步骤之一 xff0c 用来开启终端 xff0c 进行终端的初始化 xff0c 设置终端 语 法 xff1a getty h d lt
  • 进程间通信方法三:本地套接字domain

    代码中注释已写的很详细 xff0c 就不多言了 注意事项 保证套接字文件在同一个目录下网络套接字与本地套接字使用的结构体不同 网络套接字采用的结构体为struct sockaddr in本地套接字采用的结构体为struct sockaddr
  • itoa()、atoi()函数C++实现

    主要思想就是利用字符型的数字减去或加上字符型的0 xff0c 得到的就是刚好就是整型的数字 例如 0 的ASCII码为48 xff0c 4 的ASCII码为52 xff0c 4 0 61 52 47 61 4 xff0c 这样就得到数字4了
  • 自写简单的抓包程序

    需要清楚以太网帧头结构 xff0c tcp报头结构 udp报头结构 span class token macro property span class token directive keyword include span span c
  • 使用TFTP协议下载文件

    TFTP协议 最初用于引导无盘系统 xff0c 被设计用来传输小文件 TFTP基于UDP协议 TFTP的编程思想 和 UDP一样TFTP xff1a 简单文件传送协 特点 xff1a 基于UDP协议实现不进行用户有效性认证 数据传输模式 x