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. ajax向Asp.NET后端传递数组型数据

    近日,在开发一个组件的过程中,需要通过Ajax对象向Asp.NET后端传递一个比较复杂的表单,表单中的一个字段是数组类型,我能想到的办法是用JSON.stringify将前端的数组对象序列化成字符串, ...

  2. leetcode 214. 最短回文串 解题报告

    给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串.找到并返回可以用这种方式转换的最短回文串. 示例 1: 输入: "aacecaaa" 输出: "aaa ...

  3. c++知识点总结-模板特化

    类模板的全特化与偏特化 类模板 template<typename T1, typename T2> class Test { public: Test(T1 i,T2 j):a(i),b ...

  4. table不让td中文字溢出操作方法

    table不让td中文字溢出操作方法 table{ width:100px; table-layout:fixed;/* 只有定义了表格的布局算法为fixed,下面td的定义才能起作用. */ } t ...

  5. [转]mysql联合索引

    mysql联合索引   命名规则:表名_字段名1.需要加索引的字段,要在where条件中2.数据量少的字段不需要加索引3.如果where条件中是OR关系,加索引不起作用4.符合最左原则 https:/ ...

  6. nf_register_hooks解读

    nf_register_hooks是什么 net->netns_nf->nf_hook_entry[NFPROTO_NUMPROTO][NF_MAX_HOOKS=8] (nf)       ...

  7. IIS7 无法显示 htm js 图片 css的问题

    中文:开始->控件面板->程序->打开或关闭windows功能->Internet信息服务->万维网服务->常见http功能->静态内容(选中) englis ...

  8. CSS 3中细线边框如何实现?

    在app应用开发中,我们常常都需要用到css3来设置应用的样式.由于app都是在移动设备上进行展示,所以边框描边的线一般都小于1px,而以往我们使用的都是1px及以上的.那么问题来了,对于小于1px的 ...

  9. DateBase -- Rising Temperature

    Question: Given a Weather table, write a SQL query to find all dates' Ids with higher temperature co ...

  10. HDU 5761 物理题

    Rower Bo Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total ...