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. Pythonyield使用浅析

    转自:https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ 您可能听说过,带有 yield 的函数在 Python ...

  2. fiddler如何抓取夜神模拟器上的包

    一.设置Fiddler代理 1.点击Tools-Fiddler Options进入Fiddler Options页面 2.点击Connections,将Fiddler listens on port设 ...

  3. python学习总结---文件操作

    # 文件操作 ### 目录管理(os) - 示例 ```python # 执行系统命令 # 清屏 # os.system('cls') # 调出计算器 # os.system('calc') # 查看 ...

  4. 3D U-Net卷积神经网络

    3D U-Net这篇论文的诞生主要是为了处理一些块状图(volumetric images),基本的原理跟U-Net其实并无大差,因为3D U-Net就是用3D卷积操作替换了2D的,不过在这篇博文中我 ...

  5. [muku][1 初始restful api] chorme安装jsonview 插件

    https://github.com/gildas-lormeau/JSONView-for-Chrome https://www.cnblogs.com/androidstudy/p

  6. linux备忘录-文件系统管理

    Extx 文件系统原理 block group 每个分区(partition)的组成为 boot sector -> block group -> block group -> bl ...

  7. java 用Arrays.binarySearch解读 快速定位数字范围

    在一些时候,需要用给一个数字找到适合的区间,Arrays.binarySearch可达到这个目的. static int binarySearch(int[] a, int key)          ...

  8. [bzoj4361] isn [树状数组+dp+容斥原理]

    题面 传送门 思路 首先,本题目的核心元素是非降子序列,而显然这个题目中的子序列只和序列的长度.位置,以及互相之间的包含关系,这些东西相关 所以我们可以依据这些先"猜"(实际上是估 ...

  9. Educational Codeforces Round 57 (Rated for Div. 2) ABCDEF题解

    题目总链接:https://codeforces.com/contest/1096 A. Find Divisible 题意: 给出l,r,在[l,r]里面找两个数x,y,使得y%x==0,保证有解. ...

  10. bzoj1266 [AHOI2006]上学路线route floyd建出最短路图+最小割

    1266: [AHOI2006]上学路线route Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 2490  Solved: 898[Submit][S ...