美文网首页Python新世界python热爱者
Python Web开发属于自己的网盘,socket实现文件上传

Python Web开发属于自己的网盘,socket实现文件上传

作者: 48e0a32026ae | 来源:发表于2018-11-26 15:18 被阅读4次

一、说明

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

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

学习Python中有不明白推荐加入交流群

                号:516107834

                群里有志同道合的小伙伴,互帮互助,

                群里有不错的学习教程!

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 import struct

10 import sys

11

12

13 class DownloadClient:

14 """

15 下载基本流程:

16 --------------------------------------

17 客户端(Client) 服务端(Server)

18 --------------------------------------

19 读写请求 --->

20 <--- 数据包[0]

21 ACK[0] --->

22 <--- 数据包[1]

23 ACK[1] --->

24 ....

25 --------------------------------------

26

27 操作码 功能

28 --------------------------------------

29 1 读请求,即下载

30 2 写请求,即上传

31 3 表示数据包,即Data

32 4 确认码,即ACK

33 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 def start(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 def download(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 while True:

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 def upload(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 while True:

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 def show(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 Web开发属于自己的网盘,socket实现文件上传

    一、说明 本文主要基于socket实现TFTP文件上传与下载。 测试环境:Win10/Python3.5/tftp...

  • Servlet 端上传文件

    在 Web 开发中,经常遇到的一种场景就是将文件上传到服务器。比如,在需要客户信息时上传的头像;上传文件到网盘中;...

  • AjaxUpload.js简单使用

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传的简单实现.官网...

  • web框架本质

    来个简单的socket服务端 上述通过socket来实现了其本质,而对于真实开发中的python web程序来说,...

  • 文件的上传

    文件上传概述:实现web开发中的文件上传功能,需完成如下两步操作: 在web页面中添加上传输入项 在servlet...

  • 28、文件上传和下载(JavaEE笔记)

    一、文件上传概述 实现web开发中的文件上传功能,需完成如下二步操作在web页面中添加上传输入项在servlet中...

  • ruby on rails nginx 如何上传大文件?

    用ruby on rails开发的web,用了carrierwave和dropzone实现了上传文件。但后来发现,...

  • 文件上传

    前言 在Web应用系统开发中,文件上传是必不可少的功能 看完本章你将会知道 如何实现异步上传文件,并实现简单地图片...

  • Golang Web学习(15)—— 文件上传

    本文为转载,原文:Golang Web学习(15)—— 文件上传 介绍 在web开发中,对于文件上传的处理是不可避...

  • Android 文件上传

    android 文件上传主要有两种方式,HttpUrlConnection上传和Socket上传,下面贴出实现代码...

网友评论

    本文标题:Python Web开发属于自己的网盘,socket实现文件上传

    本文链接:https://www.haomeiwen.com/subject/oxybqqtx.html