Python中TFTP的理解
来源:互联网 发布:腾讯大数据 数据报告 编辑:程序博客网 时间:2024/06/03 16:39
Num01–>TFTP协议介绍
TFTP(Trivial File Transfer Protocol,简单文件传输协议)
是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文件传输的协议
特点:
1,简单
2,占用资源小
3,适合传递小文件
4,适合在局域网进行传递
5,端口号为69
6,基于UDP实现
Num02–>TFTP下载过程
TFTP服务器默认监听69号端口
当客户端发送“下载”请求(即读请求)时,需要向服务器的69端口发送
服务器若批准此请求,则使用一个新的、临时的 端口进行数据传输
当服务器找到需要现在的文件后,会立刻打开文件,把文件中的数据通过TFTP协议发送给客户端
如果文件的总大小较大(比如3M),那么服务器分多次发送,每次会从文件中读取512个字节的数据发送过来
因为发送的次数有可能会很多,所以为了让客户端对接收到的数据进行排序,所以在服务器发送那512个字节数据的时候,会多发2个字节的数据,用来存放序号,并且放在512个字节数据的前面,序号是从1开始的
因为需要从服务器上下载文件时,文件可能不存在,那么此时服务器就会发送一个错误的信息过来,为了区分服务发送的是文件内容还是错误的提示信息,所以又用了2个字节 来表示这个数据包的功能(称为操作码),并且在序号的前面
操作码 功能 1 读请求,即下载 2 写请求,即上传 3 表示数据包,即DATA 4 确认码,即ACK 5 错误
因为udp的数据包不安全,即发送方发送是否成功不能确定,所以TFTP协议中规定,为了让服务器知道客户端已经接收到了刚刚发送的那个数据包,所以当客户端接收到一个数据包的时候需要向服务器进行发送确认信息,即发送收到了,这样的包成为ACK(应答包)
为了标记数据已经发送完毕,所以规定,当客户端接收到的数据小于516(2字节操作码+2个字节的序号+512字节数据)时,就意味着服务器发送完毕了
Num03–>TFTP数据包的格式
Num04–>TFTP客户端案例编写
#! /usr/bin/env python3# -*- coding:utf-8 -*- from socket import *import struct #为了实现打包struct.pack()和拆包struct.unpack()数据import sys# python3 05-xx.py 192.168.105.125 bb.jpgdef main(): if len(sys.argv) < 3: sys.exit('usage : python3 %s ip filename' % sys.argv[0]) #server_ip = '192.168.105.125' #file_name = 'bb.jpg' server_ip = sys.argv[1] file_name = sys.argv[2] udp_socket = socket(AF_INET, SOCK_DGRAM) server_addr = (server_ip,69) # 打包数据 # !表示网络字节序,H表示2bytes无符号整数, # 5s表示长度为5字符串 # B表示1byte的无符号整数 fmt = '!H%dsB5sB' % len(file_name) send_data = struct.pack(fmt,1,file_name.encode() ,0,b'octet',0) #send_data = struct.pack(fmt,1,file_name ,0,b'octet',0) udp_socket.sendto(send_data,server_addr) f = None # 文件对象 #上一次blockNum lastBlockNum = 0 # 循环接收和应答 while True: recv_data,peer_addr = udp_socket.recvfrom(1024) # 拆包数据 opcode,blockNum = struct.unpack('!HH',recv_data[:4]) if opcode == 3: # 表示数据包 # 写入文件 # 1打开文件 # 第一次收到服务器发送数据包 if blockNum == 1: f = open(file_name,'wb') # 拆出数据 data_fmt = '!%ds' % (len(recv_data) - 4) data_content = struct.unpack(data_fmt, recv_data[4:]) # 写入文件之前判断写过没有 # if 这一次blockNum == 上一次blockNum + 1 if lastBlockNum + 1 == blockNum: #print(data_content[0]) f.write(data_content[0]) # 拆出来是元组,bytes对象,write时候需要str字符串 # 打包应答数据 ack_data = struct.pack('!HH',4,blockNum) udp_socket.sendto(ack_data,peer_addr) # 不能再给server_addr,因为端口号变了 # 当应答完毕,更新lastBlockNum lastBlockNum = blockNum # 如果数据长度小于 2 + 2 + 512 传输结束 if len(recv_data) < 516: print('over') f.close() break elif opcode == 5:# 出错 err_num = blockNum # 拆出错误信息 fmt = "!%ds" % (len(recv_data) - 5) err_msg = struct.unpack(fmt,recv_data[4:-1]) print('出错信息:%s' % err_msg) breakif __name__ == "__main__": main()
- Python中TFTP的理解
- python 中 *\的理解
- tftp 中遇到的问题
- busybox中tftp的用法
- Python中self的理解
- Python中yield的理解
- Python中iterator的理解
- Python中self的理解
- Python中self的理解
- Python中切片的理解
- Python中进程的理解
- Python中线程的理解
- Python中self的理解
- Python中数据类型的理解
- python 中Counter的理解
- Ubuntu中安装tftp/tftp-hpa服务的方法
- UTU2440开发板中tftp的使用
- RHEL5 中TFTP服务器的安装
- Android开发动态加载布局(异常状态的展示界面)
- JSON 与 Ajax
- Windows安装JDK
- pringMVC 后端代码 如何用 @requestParam() 接收前台传过来的数组
- 计算机学术会议排名
- Python中TFTP的理解
- 算法训练 Torry的困惑(基本型)
- Qt5.0 正则表达式 QRegularExpression 的使用
- UITableView 的 cell显示不完整的问题
- Android studio 汉化方法
- Matlab实现BP神经网络和RBF神经网络(二)
- 编译器与解释器的区别
- git关联Studio
- mysql用sql查询表中有多少列