实现原理见另一篇博文
https://blog.csdn.net/m0_43406494/article/details/111352876

import socket
import pdb
import os
import rebuff_size=1024
opcode={'read':b'\x00\x01','write':b'\x00\x02','data':b'\x00\x03','ack':b'\x00\x04','error':b'\x00\x05'}
error_code={1:b'\x00\x01'+b'File not found',2:b'\x00\x02'+b'Access violation',3:b'\x00\x03'+b'Disk full or allocation exceeded',4:b'\x00\x04'+b'Illegal TFTP operation',5:b'\x00\x05'+b'Unknown transfer ID',6:b'\x00\x06'+b'File already exists',7:b'\x00\x07'+b'No such user'}class tftp:def __init__(self):self.raw=b''def read(self,filename):self.raw=b''self.raw+=opcode['read']+filename.encode(encoding='utf-8', errors='ignore')+b'\x00'+b'octet'+b'\x00'def write(self,filename):self.raw=b''self.raw+=opcode['write']+filename.encode(encoding='utf-8', errors='ignore')+b'\x00'+b'octet'+b'\x00'def acknowledge(self,block):self.raw=b''self.raw+=opcode['ack']+(block).to_bytes(2,'big')def data(self,block,data):self.raw=b''self.raw+=opcode['data']+(block).to_bytes(2,'big')+datadef error(self,err):self.raw=b''self.raw+=opcode['error']+error_code[err]+b'\x00\x00'class client:def __init__(self,server_ip,server_port=69):self.server_ip=server_ipself.server_port=server_portself.soc=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#self.soc.bind(('',8888))def start(self):print('format: read/write filename')print('use cd to change current directory')print('q to quit')while 1:s=input('>')if s in ('q','Q','quit','exit'):breakif re.search('^cd',s):os.chdir(s[3:].lstrip())if s[0:4]=='read':self.read(s[5:].lstrip())elif s[0:5]=='write':self.write(s[6:].lstrip())def read(self,filename):packet=tftp()packet.read(filename)self.soc.sendto(packet.raw,(self.server_ip,self.server_port))reply=self.soc.recvfrom(buff_size)if reply[0][0:2]==opcode['error']:print('error occur:',reply[0][4:-2].decode())returnelif reply[0][0:2]==opcode['data']:totalsize=0block=0f=open(filename,'wb+')while 1:f.write(reply[0][4:])size=len(reply[0][4:])totalsize+=sizeblock+=1packet.acknowledge(block)self.soc.sendto(packet.raw,(self.server_ip,reply[1][1]))if size<512:f.close()print('receive completed.total size:{}'.format(totalsize))breakreply=self.soc.recvfrom(buff_size)def write(self,filename):file_list=os.listdir()#pdb.set_trace()if not (filename in file_list):print("file do not exist!")returnelif os.path.isdir(filename):print('{} is not a file'.format(filename))return packet=tftp()packet.write(filename)self.soc.sendto(packet.raw,(self.server_ip,self.server_port))reply=self.soc.recvfrom(buff_size)    if reply[0][0:2]==opcode['error']:print('error occur:',reply[0][4:-2].decode())returnelif reply[0][0:2]==opcode['ack']:totalsize=0block=0f=open(filename,'rb')while 1:data=f.read(512)totalsize+=len(data)block+=1packet.data(block,data)self.soc.sendto(packet.raw,(self.server_ip,reply[1][1]))reply=self.soc.recvfrom(buff_size)if len(data)<512 : print('{} sent.total size:{}'.format(filename,totalsize))breakif reply[0][0:2]==opcode['error']:print('error occur:',reply[0][4:-2].decode())breakc=client('192.168.35.130',69)
c.start()

执行脚本,可以使用cd命令来更改客户端当前的工作目录,使用q来退出
使用read/write filename的格式来上传或是下载文件

服务器在192.168.35.130,开启tftp软件作为服务器端,工作目录选择为桌面


查看服务器的日志

文件也传输到服务器的工作目录了

再从服务器读取文件

下面展示一个出现错误报文的情况
将服务器的工作目录设置为默认的安装路径

上传文件,会收到错误报文,因为要往这个路径写入文件需要更高的权限

最后说一下可以再完善的地方,在客户端上传文件给服务器时,在等待ack报文时是阻塞等待的,因此可能出现一直等待的情况,不难稍加修改变成非阻塞等待。

python实现一个简单的tftp客户端相关推荐

  1. python批量下载文件只有1kb_详解如何用python实现一个简单下载器的服务端和客户端...

    话不多说,先看代码: 客户端: import socket def main(): #creat: download_client=socket.socket(socket.AF_INET,socke ...

  2. python代理池_用Python搭建一个简单的代理池

    其实每次爬东西的时候,特怕IP被封,所以每次都要把时间延迟设置得长一点...这次用Python搭建一个简单的代理池.获取代理IP,然后验证其有效性.不过结果好像不是很理想,为什么西刺代理的高匿代理都能 ...

  3. python编写登录_通过Python编写一个简单登录功能过程解析

    通过Python编写一个简单登录功能过程解析 需求: 写一个登录的程序, 1.最多登陆失败3次 2.登录成功,提示欢迎xx登录,今天的日期是xxx,程序结束 3.要检验输入是否为空,账号和密码不能为空 ...

  4. python编写一个登陆验证程序_用python实现一个简单的验证码

    我们经常在登录一个网站,或者注册的时候需要输入一个验证码,有时候觉得很烦,因为有些验证码不仅复杂还看不清,许多用户就会因为这些而懒得再登录或者注册之类的. 既然验证码会造成流失用户的风险,为什么大家都 ...

  5. 用python写一个简单的web服务器

    人生苦短,我用python 简洁高效,这才是理想的语言啊 分享一点python的学习经验-----如何用python写一个简单的web服务器 首先,我们需要简单地了解一下网络通信协议,这里用白话介绍一 ...

  6. python实现一个简单的http服务器

    需求:用python实现一个简单的http服务器 网页源码文件:https://download.csdn.net/download/d1240673769/46963534 该文件为html文件,如 ...

  7. 后端入门之Python实现一个简单接口编写

    最近好像要转向后端了,故想提前学习下,实现一个简单接口编写,熟悉一下编写接口的流程和框架.写这个主要是记录一下自己的学习过程,以便后面温习.在Python实现一个简单接口编写之前需要了解一些后端开发的 ...

  8. python cs开发框架_用Python编写一个简单的CS架构后门的方法

    用Python编写一个简单的CS架构后门的方法 来源:中文源码网    浏览: 次    日期:2019年11月5日 [下载文档:  用Python编写一个简单的CS架构后门的方法.txt ] (友情 ...

  9. python界面设计-手把手教你用Python设计一个简单的命令行界面

    原标题:手把手教你用Python设计一个简单的命令行界面 对 Python 程序来说,完备的命令行界面可以提升团队的工作效率,减少调用时可能碰到的困扰.今天,我们就来教大家如何设计功能完整的 Pyth ...

  10. python游戏最简单代码-如何利用Python开发一个简单的猜数字游戏

    前言 本文介绍如何使用Python制作一个简单的猜数字游戏. 游戏规则 玩家将猜测一个数字.如果猜测是正确的,玩家赢.如果不正确,程序会提示玩家所猜的数字与实际数字相比是"大(high)&q ...

最新文章

  1. Spring Data(二)查询
  2. python创建数据库表空间_7.自动化监控多个Oracle表空间
  3. 调用异步服务时的超时处理
  4. python画方波_python实现周期方波信号频谱图
  5. linux c语言fifo例程,FIFO在C语言中的应用
  6. Windows、Linux及Mac查看端口和杀死进程
  7. 【已解决】报异常:java.lang.ArithmeticException: / by zero
  8. 如何获取具有日期,小时和分钟的ISO 8601格式的当前时刻?
  9. dnsmasq安装配置
  10. 2100 没有反弹shell_反弹shell | ncbash
  11. 国产6678开发记录
  12. RS485接口上的PTC
  13. python3GUI--做一款某雷影音播放器By:PyQt5
  14. 联想笔记本e43l_联想笔记本E43L的产品介绍
  15. 牛客网练习题53-A-超越学姐爱字符串题解
  16. Excel:批量将某字符替换为“换行符”
  17. spring boot 项目增加flyway的使用遇到问题解决
  18. 伊隆 马斯克经典语录英文_我写关于伊隆·麝香的信时叫我出去
  19. Java中mysql的读写分离_mysql读写分离
  20. python音乐电台推荐系统的设计与实现毕业设计源码301210

热门文章

  1. linux6禁用屏幕保护程序,禁用屏幕保护程序(ScreenSaver Disabled)
  2. 汇编语言 王爽 【第四版】 第一章 检测点1.1
  3. 怎么创建java项目?新建java项目的步骤
  4. java数据库编程--执行数据库更新操作
  5. 【CC2530入门教程-01】CC2530微控制器开发入门基础
  6. 计算机组成原理习题答案(蒋本珊)
  7. C语言system函数使用
  8. SAS Planet软件介绍与使用教程
  9. C语言程序设计(第三版)何钦铭著 习题2-2
  10. Windows Mobile 6 模拟器绿色中文版