TFTP 的基本理论


目录

  1. 通信流程
  2. 数据报文格式
  3. 传输终结
  4. 异常处理
  5. 数据丢失和超时

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是UDP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69,基于RFC1350协议。

1 通信流程 / Communication Flow

TFTP协议主要基于UDP进行,传输过程主要如下:

客户端从服务器下载:                       客户端向服务器上传:

Client----RRQ---->Server                          Client----WRQ---->Server

<----DATA----       block = 1                      <----ACK----         block = 0

----ACK---->                                          ----DATA---->       block = 1

……                                                 <----ACK----

……

其中有以下几点注意事项:

  1. Client向Server的69端口发送RRQ或者WRQ;
  2. 每个数据报文都是一个完整的block size,512bytes,发送不完整的数据包代表传输结束,若恰好为整数倍,则还需发送一个0bytes的数据报文
  3. 发送方在一定时间内没收到ACK,则需重新发送数据。

2 数据报文格式 / Data Message Format

主要包括5种数据报文格式,序号即是其opcode:

  1. RRQ        2. WRQ         3. DATA        4. ACK          5. ERROR

2.1 RRQ / WRQ packet

  2 bytes      string    1 byte   string   1 byte

----------------------------------------------------------------

|  Opcode  |  Filename  |  0  |  Mode  |  0  |

----------------------------------------------------------------

其中filename为长度不定的字符串,mode的前后均有一个比特的0作为分隔符,mode为netascii、octet或者mail之一,大小写不敏感

netascii – ascii码传输,需要发送方和接收方自己解码ascii码;

octet – 文件传输,字节模式,较为常用

mail – 邮件传输,基本不用

2.2 DATA packet

      2 bytes     2 bytes   n bytes

--------------------------------------------

|  Opcode  |  Block  |  Data  |

--------------------------------------------

数据报文格式中,Block为数据报文的序号,因为只有2个字节,所以是1-65535。当 data block是512 byte时,能接受的文件大小是512*65536=32MB,不过后面的tftp修订允许data block达到1468 byte(以太网MTU(1500)-TFTP header(4)-UDP header(8)-IP header(20)),那么能够传输的大小是1468*65535=93M。不过如果tftp实现循环利用序列号的话(65535的下一个序号是0),理论上可以传输的文件大小没有限制。

2.3 ACK packet

      2 bytes     2 bytes

------------------------------

|  Opcode  |  Block  |

------------------------------

ACK报文中,Block是应答的数据报序列号,WQR的ACK报文Block序列号为0。所有的报文都有ACK报文作为应答,除了,

  1. 重复的ACK
  2. 结束报文
  3. 报文传送超时

2.4 ERROR packet

    2 bytes      2bytes       string    1 byte

------------------------------------------------------------

|  Opcode  |  ErrorCode  |  ErrMsg  |  0  |

------------------------------------------------------------

错误报文的格式如上所示,Opcode是5,ErrorCode是错误代码,ErrMsg是错误信息,结尾以一个比特的0作为分隔符。

2.5 加解码packet

加解码的方式可按照下面的示例代码完成,其中用到了 struct 模块

 import struct
RRQ = 1
WRQ = 2
DATA = 3
ACK = 4
ERROR = 5 class TFTPReadWriteRequest():
@staticmethod
def encode(op, file_name, mode='octet'):
opcode_select = {'r': RRQ, 'w': WRQ}
opcode = opcode_select[op]
packet = struct.pack('!H%dsb%dsb' % (len(file_name), len(mode)), opcode, file_name.encode(), 0, mode.encode(), 0)
return packet @staticmethod
def decode(msg_bytes):
opcode = struct.unpack('!H', msg_bytes[:2])[0]
fileName = msg_bytes[2:].decode('utf-8').split('\x00')[0]
mode = msg_bytes[2:].decode('utf-8').split('\x00')[1]
print('=== Transfer mode is %s' % mode)
return opcode, fileName class TFTPData():
@staticmethod
def encode(block_number, data):
packet = b'\x00\x03'
packet += struct.pack('!H', block_number)
packet += data
return packet @staticmethod
def decode(data_msg):
opcode = struct.unpack('!HH', data_msg[:4])[0]
block_num = struct.unpack('!HH', data_msg[:4])[1]
data = data_msg[4:]
return opcode, block_num, data class TFTPAck():
@staticmethod
def encode(block_num):
packet = b''
packet += b'\x00\x04'
packet += struct.pack('!H', block_num)
return packet @staticmethod
def decode(msg_bytes):
opcode = struct.unpack('!HH', msg_bytes)[0]
ack_block = struct.unpack('!HH', msg_bytes)[1]
return opcode,ack_block class ErrorOpcode(Exception):
pass

3 传输终结 / Transmission End

传输终结的标志是传输数据小于512bytes,当接收方收到最后一个数据报文时,仍然需要发送ACK应答(对于接收端意义不大,但发送端需进行确认),在发送完ACK应答后,还需要等待一段时间(默认的超时时间),如果还是收到了发送端发送的最后一个数据报文,说明发送端没收到ACK报文,需要再次发送,直到在等待时间里没有收到数据报文,或者超过了默认的最大重发次数

4 异常处理 / Error Handle

当发送过程中出现错误或者请求无法满足,就会发送ERROR报文,ERROR报文是发完就不管的,没有重发机制,需要接收方借助超时机制来检测错误。错误代码如下:

  0 – Not defined, see error message (if any)

  1 – File not found

  2 – Access violation

  3 – Disk full or allocation exceeded

  4 – Illegal TFTP operation

  5 – Unknown transfer ID

  6 – File already exists

  7 – No such user

5 数据丢失和超时 / Data Loss and Time out

TFTP没有提供报文的错误检查机制,即认为所有接收的报文都是正确的,数据丢失和对端主机服务无法访问等错误需要借助超时机制来检测,在每次发送一个报文的时候,需要设置一个计时器,如果在计时器超时的时候还没有收到下一个数据,则重发上次的报文。如果计时器超时次数超过了最大值,则终止程序。当接收到新的报文时,不管报文正确还是重复,都要重置计时器

相关阅读


1. struct 模块

2. TFTP 通信的 Python 实现

参考链接


http://cizixs.com/2015/04/12/write-tftp-with-python-1

http://blog.csdn.net/u014745194/article/details/71479669

http://blog.csdn.net/u014745194

Python的网络编程[2] -> TFTP 协议[0] -> TFTP 的基本理论的更多相关文章

  1. Python的网络编程[3] -> BOOTP 协议[0] -> BOOTP 的基本理论

    BOOTP协议 / BOOTP Protocol 目录 基本理论 BOOTP 与 DHCP 通信流程 数据报文格式 报文加解码实现 1. 基本理论 / Basic Theory BOOTP(Boots ...

  2. Python的网络编程[1] -> FTP 协议[0] -> FTP 的基本理论

    FTP协议 / FTP Protocol FTP全称为File Transfer Protocol(文件传输协议),常用于Internet上控制文件的双向传输,常用的操作有上传和下载.基于TCP/IP ...

  3. Python的网络编程[4] -> DHCP 协议[0] -> DHCP 的基本理论

    DHCP协议 / DHCP Protocol 目录 DHCP 基本理论 DHCP 通信流程 DHCP 完整报文 DHCP 的 Optional 字段 DHCP 的报文类型 1 DHCP 基本理论 DH ...

  4. Python的网络编程[3] -> BOOTP 协议[1] -> BOOTP 的 Python 实现

    BOOTP实现 / BOOTP Implement 目录 BOOTP 的服务器建立过程 BOOTP 的客户端建立过程 Note: 理论部分请参考文末相关阅读链接 1 BOOTP 的服务器建立过程 服务 ...

  5. Python的网络编程[6] -> Modbus 协议 -> Modbus 的基本理论与 Python 实现

    Modbus协议 / Modbus Protocol 目录 Modbus 协议简介 Modbus RTU协议 Modbus TCP协议与 Python 实现 Modbus 功能码 Modbus TCP ...

  6. Python的网络编程[1] -> FTP 协议[2] -> 使用 ftplib 建立 FTP 客户端

    使用 ftplib 建立 FTP 客户端 用于建立FTP Client,与 pyftplib 建立的 Server 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 客户端 1. 模块信息 1 ...

  7. Python的网络编程[4] -> DHCP 协议[1] -> DHCP 的 Python 实现

    DHCP实现 / DHCP Implement 目录 DHCP 服务器建立过程 DHCP 报文加码实现过程 下面介绍建立一个简单的DHCP服务器,主要用于对基本的DHCP请求进行响应,目前只提供一个I ...

  8. Python的网络编程[1] -> FTP 协议[1] -> 使用 pyftplib 建立 FTP 服务器

    使用 pyftplib 建立 FTP 服务器 pyftplib 主要用于建立 FTP Server,与 ftplib 建立的 Client 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 服 ...

  9. python之网络编程

    本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...

随机推荐

  1. Pascal小游戏 俄罗斯方块

    俄罗斯方块已经成为了和“Hello World”一样的程序了吧? 不要直接复制,可能需要事先 Format. program cube;uses crt,graph,dos;var gd,gm:sma ...

  2. flask 基础ssti注入

    源代码地址 (请用python2.7运行,python3有点出入) 注入点: 不是返回的静态模板而是反回模板字符串变得让客户端可以控制. XSS 这里直接 http://39.105.116.195: ...

  3. SQL面试题:之一(难度:中等)

    SQL面试题:之一(难度:中等)

  4. 孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘

    孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我 ...

  5. 编译caffe遇到的问题

    1. failed to see hdf5.h https://askubuntu.com/questions/629654/building-caffe-failed-to-see-hdf5-h 2 ...

  6. SVN客户端使用手册

    使用svn进行源代码版本控制,代码管理利器. 优点: 使用方便,与文件管理器集成.速度快,稳定. 实现代码比较,比如对历史和当前代码进行比较. 解决多人同时编写代码时代码重复修改困难. 安装: 下载网 ...

  7. mysql备份策略

    1.备份的种类 完全备份,就是备份整个数据库对象 事务日志备份, 备份事务日志记录上一次的数据库改变 增量备份,也叫差异备份 文件备份 2.备份方式 逻辑备份, 既备份sql语句,使用mysql自带的 ...

  8. hdu 1211 RSA (逆元)

    RSA Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  9. 2017 多校2 hdu 6053 TrickGCD

    2017 多校2 hdu 6053 TrickGCD 题目: You are given an array \(A\) , and Zhu wants to know there are how ma ...

  10. Where to Run LightOJ - 1287(概率dp)

    Where to Run LightOJ - 1287(概率dp) 题面长长的,看了半天也没看懂题意 不清楚的地方,如何判断一个点是否是EJ 按照我的理解 在一个EJ点处,要么原地停留五分钟接着走,要 ...