Python的网络编程[2] -> TFTP 协议[0] -> TFTP 的基本理论
TFTP 的基本理论
目录
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----
……
其中有以下几点注意事项:
- Client向Server的69端口发送RRQ或者WRQ;
- 每个数据报文都是一个完整的block size,512bytes,发送不完整的数据包代表传输结束,若恰好为整数倍,则还需发送一个0bytes的数据报文
- 发送方在一定时间内没收到ACK,则需重新发送数据。
2 数据报文格式 / Data Message Format
主要包括5种数据报文格式,序号即是其opcode:
- 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报文作为应答,除了,
- 重复的ACK
- 结束报文
- 报文传送超时
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 模块
参考链接
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 的基本理论的更多相关文章
- Python的网络编程[3] -> BOOTP 协议[0] -> BOOTP 的基本理论
BOOTP协议 / BOOTP Protocol 目录 基本理论 BOOTP 与 DHCP 通信流程 数据报文格式 报文加解码实现 1. 基本理论 / Basic Theory BOOTP(Boots ...
- Python的网络编程[1] -> FTP 协议[0] -> FTP 的基本理论
FTP协议 / FTP Protocol FTP全称为File Transfer Protocol(文件传输协议),常用于Internet上控制文件的双向传输,常用的操作有上传和下载.基于TCP/IP ...
- Python的网络编程[4] -> DHCP 协议[0] -> DHCP 的基本理论
DHCP协议 / DHCP Protocol 目录 DHCP 基本理论 DHCP 通信流程 DHCP 完整报文 DHCP 的 Optional 字段 DHCP 的报文类型 1 DHCP 基本理论 DH ...
- Python的网络编程[3] -> BOOTP 协议[1] -> BOOTP 的 Python 实现
BOOTP实现 / BOOTP Implement 目录 BOOTP 的服务器建立过程 BOOTP 的客户端建立过程 Note: 理论部分请参考文末相关阅读链接 1 BOOTP 的服务器建立过程 服务 ...
- Python的网络编程[6] -> Modbus 协议 -> Modbus 的基本理论与 Python 实现
Modbus协议 / Modbus Protocol 目录 Modbus 协议简介 Modbus RTU协议 Modbus TCP协议与 Python 实现 Modbus 功能码 Modbus TCP ...
- Python的网络编程[1] -> FTP 协议[2] -> 使用 ftplib 建立 FTP 客户端
使用 ftplib 建立 FTP 客户端 用于建立FTP Client,与 pyftplib 建立的 Server 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 客户端 1. 模块信息 1 ...
- Python的网络编程[4] -> DHCP 协议[1] -> DHCP 的 Python 实现
DHCP实现 / DHCP Implement 目录 DHCP 服务器建立过程 DHCP 报文加码实现过程 下面介绍建立一个简单的DHCP服务器,主要用于对基本的DHCP请求进行响应,目前只提供一个I ...
- Python的网络编程[1] -> FTP 协议[1] -> 使用 pyftplib 建立 FTP 服务器
使用 pyftplib 建立 FTP 服务器 pyftplib 主要用于建立 FTP Server,与 ftplib 建立的 Client 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 服 ...
- python之网络编程
本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...
随机推荐
- 《Cracking the Coding Interview》——第16章:线程与锁——题目6
2014-04-27 20:25 题目:关于java中标有synchronized的成员方法? 解法:这代表同一个对象实例的synchronized方法不能被多个线程同时调用.注意有这么多个地方都加粗 ...
- 随笔 —— 门徒 & 无限恐怖
门徒 忧思缠身,所为何物 不知何人,可免世俗 每每朝暮,心无释处 悲从中来,如泣如诉 仁者存世,满怀悲苦 逝者如斯,追还无路 上天无门,开怀捧腹 无路偏行,我行我素 无限恐怖 饥寒苦难谁知故,日日行路 ...
- 使用Html5shiv.js让ie支持html5
ie低版本不支持html5标签,可以引入一段脚本,在ie浏览器中创建html5的标签. 1,可以在网上下载html5shiv的压缩包,引入压缩版的html5shiv.min.js即可. 脚本引用要在h ...
- selenium初识(一)
Selenium是一个开源的便携式的自动化软件测试工具,用于测试web应用程序.有能力在不同浏览器和操作系统运行.它是一套工具,帮助我们有效地给予web应用程序的自动化. Selenium分为以下几个 ...
- Ubuntu15.04 python升级到python-3.6.x
简略记录步骤,容后补充: sudo add-apt-repository ppa:jonathonf/python-3.6 sudo apt-get update sudo apt-get i ...
- HDU 4474 Yet Another Multiple Problem ( BFS + 同余剪枝 )
没什么巧办法,直接搜就行. 用余数作为每个节点的哈希值. #include <cstdio> #include <cstring> #include <cstdlib&g ...
- atan与atan2的区别
相比较ATan,ATan2究竟有什么不同?本篇介绍一下ATan2的用法及使用条件. 对于tan(θ) = y / x: θ = ATan(y / x)求出的θ取值范围是[-PI/2, PI/2]. θ ...
- CSLA多语言设置
1.在程序运行文件夹例如“\Bin\Debug\”中包含csla生成的资源文件: 2.在程序运行时,设置CSLA的当前语言为你想要的语言,例如:Csla.Properties.Resources.Cu ...
- 【bzoj4636】蒟蒻的数列 离散化+线段树
原文地址:http://www.cnblogs.com/GXZlegend/p/6801379.html 题目描述 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个 ...
- Codeforces Round #384 (Div. 2) 734E(二分答案+状态压缩DP)
题目大意 给定一个序列an,序列中只有1~8的8个整数,让你选出一个子序列,满足下列两个要求 1.不同整数出现的次数相差小于等于1 2.子序列中整数分布是连续的,即子序列的整数必须是1,1,1.... ...