一、说明

本文主要基于socket实现TFTP文件上传与下载。

测试环境:Win10/Python3.5/tftpd64。

tftpd下载:根据自己的环境选择下载,地址 :http://tftpd32.jounin.net/tftpd32_download.html

主要内容:TFTP协议介绍、程序运行图示和分析fmt、源代码。

二、TFTP协议介绍(参考网络,详情可搜索)

TFTP(Trivial File Transfer Protocol,简单文件传输协议),是TCP/IP协议族中的一个用来在客户端与服务端(C/S架构)之间进行文件传输的协议。

1、特点:

> 简单、占用资源少

> 适合小文件传输

> 适合在局域网中进行传输

> 端口号为69

> 基于UDP实现

2、TFTP下载过程分析:

当打开一个tftpd作为服务端,会默认监听69端口,所以客户端发送数据到服务端都是经过69端口。

下载的数据流过程如上图所示,客户端首次发送需要下载的文件名到服务端,(文件存在)服务端收到后会返回该文件的第一个包,客户端收到后本地保存然后再发送ACK应答包给服务端,如此往来多次,一发一答,即实现了文件的下载。

3、TFTP操作码与数据格式:

4、差错码以及对应的提示:

5、TFTP上传过程分析(此处做简单文件说明,可参考下面源码或自行搜索):

上传的基本流程:客户端发送写请求(操作码为2)到服务端,如果可以进行上传,服务端会返回ACK应答包,客户端收到后即可进行第一个数据包发送,进而服务端收到后会返回ACK应打包,如此多次,当客户端文件读取完成,即可退出上传,此时上传完成。

三、程序运行图示和分析fmt

1、运行起来的tftpd服务端如下所示:

选择作为下载的路径和配置IP

2、下载过程:

运行脚本传入两个参数:服务端IP和文件名

3、上传过程:

4、关于struct.pack() 和 struct.unpack()的参数说明:

参考:https://blog.csdn.net/DaxiaLeeSuper/article/details/82018070

struct.pack(b"!H7sb5sb", b"test.png", 0, b"octet", 0 )

主要分析第一个参数 fmt:如 “!H7sb5sb" => [ 1, b"test.png", 0, b"octet", 0  ]

fmt对后面几个参数说明,其中H代表1,7s表示长度为7的字符串等

1、fmt首个字符:

2、fmt其他字符:

四、源码

1 #-*- coding:utf-8 -*-

2

3 """

4 实现 TFTP 上传与下载功能5 需要配合tftpd 软件测试6 """

7

8 from socket import *

9 importstruct10 importsys11

12

13 classDownloadClient:14 """

15 下载基本流程:16 --------------------------------------17 客户端(Client) 服务端(Server)18 --------------------------------------19 读写请求 --->20 22 24 ....25 --------------------------------------26

27 操作码 功能28 --------------------------------------29 1 读请求,即下载30 2 写请求,即上传31 3 表示数据包,即Data32 4 确认码,即ACK33 5 错误34 --------------------------------------35 """

36 def __init__(self):37 #读取参数

38 if len(sys.argv) != 4:39 print("-" * 30)40 print("Tips:")41 print("python xxx.py 1 127.0.0.1 test.png")42 print("-" * 30)43 exit()44 else:45 self.mid = sys.argv[1] #执行的方法,1下载或2上传

46 self.remoteIp = sys.argv[2] #服务器IP

47 self.filename = sys.argv[3] #下载文件名

48

49 #创建socket实例

50 self.socketClient =socket(AF_INET, SOCK_DGRAM)51 self.socketClient.bind(('', 7788))52

53 defstart(self):54 """启动执行"""

55 if self.mid == "1":56 self.download()57 elif self.mid == "2":58 self.upload()59 else:60 print(self.mid)61 print("参数输入错误 [python 脚本名 方法id(1下载,2上传) 服务器IP 文件名]:python xxx.py 1 127.0.0.1 test.png")62 exit()63

64 defdownload(self):65 """TFTP 下载"""

66 print("下载启动...")67

68 #构建下载请求数据

69 #第一个参数 !H7sb5sb = "!H"+str(len(filename))+"sb5sb"

70 filenameLen =str(len(self.filename))71 cmdBuf = struct.pack(("!H%ssb5sb" % filenameLen).encode("utf-8"), 1, self.filename.encode("utf-8"), 0, b"octet", 0)72

73 #发送下载文件请求数据到指定服务器

74 self.socketClient.sendto(cmdBuf, (self.remoteIp, 69))75

76 #self.show()

77

78 locPackNum = 0 #请求包号

79 saveFile = '' #保存文件句柄

80 whileTrue:81 recvData, recvAddr = self.socketClient.recvfrom(1024)82 recvDataLen =len(recvData)83

84 #解包

85 cmdTuple = struct.unpack(b"!HH", recvData[:4])86 cmd = cmdTuple[0] #指令

87 curPackNum = cmdTuple[1] #当前包号

88

89 if cmd == 3: #是否为数据包

90 if curPackNum == 1:91 #以追加的方式打开文件

92 saveFile = open(self.filename, "ab")93

94 #包编号是否和上次相等

95 if locPackNum + 1 ==curPackNum:96 saveFile.write(recvData[4:]) #写入数据

97 locPackNum += 1

98

99 #发送ACK应答

100 ackBuf = struct.pack(b"!HH", 4, locPackNum)101 self.socketClient.sendto(ackBuf, recvAddr)102

103 print("(%d)次接收到数据" %locPackNum)104

105 #确认为最后一个包

106 if recvDataLen < 516:107 saveFile.close()108 print("已经下载完成")109 break

110

111 elif cmd == 5: #是否为错误应答

112 print("error num:%d" %curPackNum)113 break

114

115 defupload(self):116 """TFTP 上传"""

117 print("上传启动...")118

119 #1、发送读请求

120 filenameLen =str(len(self.filename))121 cmdBuf = struct.pack(("!H%ssb5sb" % filenameLen).encode("utf-8"), 2, self.filename.encode("utf-8"), 0, b"octet", 0)122

123 self.socketClient.sendto(cmdBuf, (self.remoteIp, 69))124

125 localPackNum = 1 #本地包号

126 sendFile = '' #文件句柄

127 whileTrue:128 #2、接收回复

129 recvData, recvAddr = self.socketClient.recvfrom(1024)130

131 #3、解包

132 cmdTuple = struct.unpack(b"!HH", recvData[:4])133 cmd = cmdTuple[0] #指令

134 curPackNum = cmdTuple[1] #当前包号

135

136 #print(recvData)

137

138 if cmd == 4:139 #打开并读取文件

140 if curPackNum ==0:141 sendFile = open(self.filename, "rb")142

143 #ACK应答的包号是否与本地的一样

144 if localPackNum - 1 ==curPackNum:145 #4、读取 512 byte数据

146 sendData = sendFile.read(512)147

148 #判断文件是否读取完成

149 if len(sendData) <=0:150 sendFile.close()151 print("上传完成")152 break

153

154 #5、打包发送数据

155 sendDataBuf = struct.pack(b"!HH512s", 3, localPackNum, sendData)156 self.socketClient.sendto(sendDataBuf, recvAddr)157

158 #打印过程

159 print("(%d)次已发送,数据长度:%d" %(localPackNum, len(sendData)))160 localPackNum += 1

161

162 elif cmd == 5:163 #sendFile.close()

164 print("error num:%d" %curPackNum)165 break

166

167 defshow(self):168 """测试打印数据"""

169 recvData = self.socketClient.recvfrom(1024)170 print(recvData)171 exit()172

173

174 if __name__ == "__main__":175 demo =DownloadClient()176 demo.start()

python实现文件上传和下载_[Python] socket实现TFTP上传和下载相关推荐

  1. mysql管理数据 并上传至云端_怎样将MySQL数据库上传到服务器

    首先,需要将本地的数据库导出来,作为一个数据文件,以备稍后上传到服务器用,在本地登陆phpmyadmin控制面板: 登陆成功后,在左侧选择需要操作的数据库: 选择后,页面会自动刷新,然后再在右边点击[ ...

  2. python打开文件报错无效序列_解决Python 写文件报错TypeError的问题

    处理上传的文件: f1 = request.FILES['pic'] fname = '%s/%s' % (settings.MEDIA_ROOT, f1.name) with open(fname, ...

  3. python写文件追加 按行追加_你真的会用python进行文件操作吗

    本篇文章主要比较系统的介绍了python中文件操作,以及在在使用中需要注意的问题. 什么是文件 文件是系统存储区域的一个命名位置,用来存储一些信息,便于后续访问.能够在非易失性存储器中实现持续性存储, ...

  4. gke下载_我们如何在GKE上升级Kubernetes

    gke下载 Gojek Long阅读 (Gojek Long Reads) If you're running Kubernetes on GKE, chances are there's alrea ...

  5. java上传图文消息_微信公众号开发之上传图文消息素材(十二)

    群发消息太重要了,公众号管理员需要定期通过公众号群发一些消息,用户通过推送的消息可以定期了解公众号的最新信息. 群发图文消息的过程如下: 首先,预先将图文消息中需要用到的图片,使用上传图文消息内图片接 ...

  6. 手机python编程文件如何转文档_(转)Python之文件读写

    原文:https://www.cnblogs.com/huilixieqi/p/6494891.html 本节内容: I/O操作概述 文件读写实现原理与操作步骤 文件打开模式 Python文件操作步骤 ...

  7. xbox360游戏下载_如何在Xbox One上玩Xbox 360游戏

    xbox360游戏下载 Microsoft's Xbox One can now play a limited number of Xbox 360 games. But it's not as si ...

  8. python发送文件到钉钉群_iOS python 自动化打包,并在钉钉群里发通知

    最近感觉iOS 打包给测试人员测试,用Xcode 打包太费经了.项目编译太慢,一次打包可能需要20来分钟.于是就想用下自动化打包.本来想尝试下Fastlane 或者jenkins 但是觉得还是有点麻烦 ...

  9. android 快传 源码_最新安卓仿茄子快传APP源码包括服务端源码Android开发快传类项目源码全套...

    适使用范围:  安卓APP茄子快传源码 Android项目源码相似茄子快传的快传项目包括服务端 运行环境:  Android app 源码详细: 本项目是一个基于安卓的相似茄子快传的项目源码,包括安卓 ...

最新文章

  1. 华为公有云架构解决方案
  2. 统计学:统计学概述(一)
  3. iOS10 UI教程视图的几何形状
  4. 001/Docker入门(Mooc)
  5. MP4文件格式带数据详解
  6. 七月在线 《关键点检测概览与环境配置》
  7. 动态规划—最长公共子序列
  8. 2018.12.18运算符,分支结构(循环),异常处理,函数
  9. 牛逼!支付宝高级Java三面题目:线程锁+事务+雪崩+Docker等
  10. spring boot / cloud (七) 使用@Retryable来进行重处理
  11. llinux c 语言延时,linux下写个C语言程序,要求有0.5微秒以下的延时,要怎样写
  12. 深入Linux grep指令的详解(实用型)
  13. 公里导线时有没有计算机类计算方法,基于Matlab的导线网坐标计算. (1).doc
  14. 仿网易严选Flutter项目
  15. word文档页码从正文页开始编号
  16. keil优化等级影响STM32 GPIO速度变化
  17. CorelDRAW2022订阅版本最新更新内容
  18. springboot+Rabit实战二:(Rabbit MQ web 界面管理)
  19. Vue 点击获得父元素,子元素,兄弟元素(DOM操作)
  20. 出生日期转化为岁月天

热门文章

  1. 查看swintransformer的网络结构
  2. spyder的输出面板不小心关掉了怎么办?
  3. linux vnc的小黑点和鼠标不同步_vnc使用教程,在Linux中vnc使用教程的4个步骤
  4. 操作云数据库出现Access denied for user ‘common_1‘@‘%‘ to database ‘seata_storage‘
  5. 《操作系统》课程设计报告——用JAVA语言模仿实现“吃水果”问题
  6. 维吉尼亚c语言编码原理,维吉尼亚密码的C语言实现.doc
  7. java jpa注解哪个包好,Spring Data JPA 中常用注解详解
  8. 2021年 研考 国家线 公布
  9. Android Json处理框架
  10. MySQL优化之my.conf配置详解