1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
本实验实现ftp上传文件下载文件功能,并具有校验文件完整性,打印进度条功能,
主要练习socket,struct模块。
ftp用户文件存放在user.json文件中
user.json文件内容
{
"lisi"
:
"abcdef"
,
"hyh"
:
"123456"
}
ftp客户端脚本ftpclient.py
#!/usr/bin/python
# --*-- coding: utf-8 --*--
import
socket
import
json
import
time
import
sys
import
struct
from
hashlib
import
md5
ftp_obj
=
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ftp_obj.connect((
'127.0.0.1'
,
8080
))
def
login_auth(ftp_obj):
"""用户登录三次认证,输入用户名密码跟服务器账号密码匹配返回True,否则返回False"""
count
=
0
while
count <
3
:
user_name
=
input
(
"请输入账户: "
).strip()
user_passwd
=
input
(
"请输入密码: "
).strip()
if
user_name
and
user_passwd:
ftp_obj.send(user_name.encode(
'utf-8'
))
ftp_obj.send(user_passwd.encode(
'utf-8'
))
else
:
count
+
=
1
continue
#time.sleep(10)
login_res_bytes
=
ftp_obj.recv(
1024
)
# print(login_res_bytes)
# print(login_res_bytes.decode('gbk'))
login_res
=
login_res_bytes.decode(
'gbk'
)
if
login_res
=
=
'True'
:
return
True
else
:
count
+
=
1
continue
else
:
return
False
def
progress_bar(num, total):
"""打印进度条"""
rate
=
num
/
total
rate_num
=
int
(rate
*
100
)
r
=
'\r%s%d%%'
%
(
'#'
*
rate_num, rate_num,)
print
(r)
def
get_md5(data):
"""校验文件内容"""
m
=
md5()
m.update(data.encode(
'utf-8'
))
res
=
m.hexdigest()
return
res
def
ftp_cmd(ftp_obj):
"""上传下载命令"""
while
True
:
cmd
=
input
(
"请输入命令(dir or put filepath or get filepath or exit)>>: "
).strip()
if
cmd
=
=
'exit'
:
sys.exit(
0
)
#print(cmd_list)
if
cmd
=
=
'dir'
:
ftp_obj.send(cmd.encode(
'utf-8'
))
head_struct
=
ftp_obj.recv(
4
)
head_len
=
struct.unpack(
'i'
, head_struct)[
0
]
head_bytes
=
ftp_obj.recv(head_len)
head_json
=
head_bytes.decode(
'utf-8'
)
head_dict
=
json.loads(head_json)
total_size
=
head_dict[
'total_size'
]
recv_size
=
0
data
=
b''
while
recv_size < total_size:
recv_data
=
ftp_obj.recv(
1024
)
data
+
=
recv_data
recv_size
+
=
len
(recv_data)
print
(data.decode(
'gbk'
))
else
:
cmd_list
=
cmd.split()
if
cmd_list[
0
]
=
=
'get'
:
ftp_obj.send(cmd.encode(
'utf-8'
))
head_struct
=
ftp_obj.recv(
4
)
head_len
=
struct.unpack(
'i'
, head_struct)[
0
]
head_bytes
=
ftp_obj.recv(head_len)
head_json
=
head_bytes.decode(
'utf-8'
)
head_dict
=
json.loads(head_json)
total_size
=
head_dict[
'total_size'
]
recv_size
=
0
data
=
b''
while
recv_size < total_size:
recv_data
=
ftp_obj.recv(
1024
)
data
+
=
recv_data
recv_size
+
=
len
(recv_data)
progress_bar(recv_size, total_size)
#打印进度条,传入两个参数,第一个是接受的数据字节,第二个是数据头解包的数据总长度
with
open
(cmd_list[
1
],
'w'
, encoding
=
'utf-8'
) as f:
f.write(data.decode(
'utf-8'
))
check_md5
=
get_md5(data.decode(
'utf-8'
))
#校验传输的内容
if
head_dict[
'hashlib'
]
=
=
check_md5:
print
(
"下载成功,文件内容完整"
)
else
:
print
(
"下载完成,文件内容不完整"
)
elif
cmd_list[
0
]
=
=
'put'
:
ftp_obj.send(cmd.encode(
'utf-8'
))
with
open
(cmd_list[
1
],
'r'
, encoding
=
'utf-8'
) as f:
data
=
f.read()
check_put_md5
=
get_md5(data)
head_dict
=
{
'filename'
: cmd_list[
1
],
'hashlib'
: check_put_md5,
'total_size'
:
len
(data)}
head_json
=
json.dumps(head_dict)
head_bytes
=
head_json.encode(
'utf-8'
)
ftp_obj.send(struct.pack(
'i'
,
len
(head_bytes)))
ftp_obj.send(head_bytes)
is_upload
=
ftp_obj.recv(
10
)
if
is_upload.decode(
'gbk'
)
=
=
'True'
:
#ftp_obj.send(data.encode('utf-8'))
with
open
(cmd_list[
1
],
'r'
, encoding
=
'utf-8'
) as f:
dataline
=
f.readlines()
data_len
=
0
for
i
in
dataline:
ftp_obj.send(i.encode(
'utf-8'
))
data_len
+
=
len
(i)
time.sleep(
0.1
)
progress_bar(data_len,
len
(data))
print
(
"上传成功"
)
is_check
=
ftp_obj.recv(
10
)
if
is_check.decode(
'gbk'
)
=
=
'True'
:
print
(
"文件上传完整"
)
else
:
print
(
"文件上传不完整"
)
else
:
print
(
"文件太大,超出磁盘限额"
)
continue
else
:
print
(
"命令错误,重重新输入"
)
continue
def
main():
auth_res
=
login_auth(ftp_obj)
if
auth_res:
ftp_cmd(ftp_obj)
else
:
print
(
"用户或密码不正确,退出程序"
)
sys.exit(
1
)
if
__name__
=
=
'__main__'
:
main()
ftp服务端脚本ftpserver.py
#!/usr/bin/python
# --*-- coding:utf-8
import
socket
import
json
import
os
import
subprocess
import
struct
from
hashlib
import
md5
import
time
dir
=
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
hyh_size
=
5
#'hyh'用户M空间限额5M
lisi_size
=
10
#'lisi'用户空间限额10M
ftp_obj
=
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ftp_obj.bind((
'127.0.0.1'
,
8080
))
ftp_obj.listen(
5
)
def
size(user_home_dir):
"""计算用户家目录大小"""
# print(user_home_dir)
# print(os.listdir(user_home_dir))
file_size_bytes
=
0
for
i
in
os.listdir(user_home_dir):
file
=
user_home_dir
+
'\\'
+
i
file_size_bytes
+
=
os.path.getsize(
file
)
file_size_mbytes
=
file_size_bytes
/
(
1024
*
1024
)
return
file_size_mbytes
def
get_md5(data):
"""校验文件内容"""
m
=
md5()
m.update(data.encode(
'utf-8'
))
res
=
m.hexdigest()
return
res
def
ftp_load(conn, user_name):
"""接收客户端命令,并执行"""
user_home_dir
=
dir
+
'\\'
+
user_name
used_size
=
size(user_home_dir)
while
True
:
try
:
print
(
'开始接收发送数据'
)
cmd_res_bytes
=
conn.recv(
1024
)
cmd_res
=
cmd_res_bytes.decode(
'utf-8'
)
if
cmd_res
=
=
'dir'
:
res
=
subprocess.Popen(cmd_res
+
' '
+
user_home_dir, shell
=
True
, stdout
=
subprocess.PIPE, stderr
=
subprocess.PIPE)
err
=
res.stderr.read()
if
err:
cmd_stdout
=
err
else
:
cmd_stdout
=
res.stdout.read()
#print(cmd_stdout.decode('gbk'))
head_dict
=
{
'dir'
: user_name,
'hashlib'
:
None
,
'total_size'
:
len
(cmd_stdout)}
head_json
=
json.dumps(head_dict)
head_bytes
=
head_json.encode(
'utf-8'
)
conn.send(struct.pack(
'i'
,
len
(head_bytes)))
conn.send(head_bytes)
conn.send(cmd_stdout)
else
:
cmd_res_list
=
cmd_res.split()
#获取命令和文件列表
user_home_file
=
user_home_dir
+
'\\'
+
cmd_res_list[
1
]
#获取文件
if
cmd_res_list[
0
]
=
=
'get'
:
with
open
(user_home_file,
'r'
, encoding
=
'utf-8'
) as f:
data
=
f.read()
check_md5
=
get_md5(data)
#校验文件内容md5
head_dict
=
{
'filename'
: cmd_res_list[
1
],
'hashlib'
: check_md5,
'total_size'
:
len
(data)}
head_json
=
json.dumps(head_dict)
head_bytes
=
head_json.encode(
'utf-8'
)
conn.send(struct.pack(
'i'
,
len
(head_bytes)))
conn.send(head_bytes)
with
open
(user_home_file,
'r'
, encoding
=
'utf-8'
) as f:
dataline
=
f.readlines()
for
i
in
dataline:
time.sleep(
0.1
)
conn.send(i.encode(
'utf-8'
))
#conn.send(data.encode('utf-8'))
else
:
head_struct
=
conn.recv(
4
)
head_len
=
struct.unpack(
'i'
, head_struct)[
0
]
head_bytes
=
conn.recv(head_len)
head_json
=
head_bytes.decode(
'utf-8'
)
head_dict
=
json.loads(head_json)
total_size
=
head_dict[
'total_size'
]
if
user_name
=
=
'hyh'
:
if
hyh_size
-
used_size > total_size
/
(
1024
*
1024
):
conn.send(
'True'
.encode(
'utf-8'
))
recv_size
=
0
data
=
b''
while
recv_size < total_size:
recv_data
=
conn.recv(
1024
)
data
+
=
recv_data
recv_size
+
=
len
(recv_data)
with
open
(user_home_file,
'w'
, encoding
=
'utf-8'
) as f:
f.write(data.decode(
'utf-8'
))
check_put_md5
=
get_md5(data.decode(
'utf-8'
))
if
head_dict[
'hashlib'
]
=
=
check_put_md5:
conn.send(
'True'
.encode(
'utf-8'
))
continue
else
:
conn.send(
'False'
.encode(
'utf-8'
))
continue
else
:
conn.send(
'False'
.encode(
'utf-8'
))
continue
elif
user_name
=
=
'lisi'
:
if
lisi_size
-
used_size > total_size
/
(
1024
*
1024
):
conn.send(
'True'
.encode(
'utf-8'
))
recv_size
=
0
data
=
b''
while
recv_size < total_size:
recv_data
=
conn.recv(
1024
)
data
+
=
recv_data
recv_size
+
=
len
(recv_data)
with
open
(user_home_file,
'w'
, encoding
=
'utf-8'
) as f:
f.write(data.decode(
'utf-8'
))
continue
else
:
conn.send(
'False'
.encode(
'utf-8'
))
continue
else
:
continue
except
Exception:
break
while
True
:
print
(
'waitting to accept...'
)
conn, addr
=
ftp_obj.accept()
print
(
'client: '
, addr)
while
True
:
try
:
user_name_bytes
=
conn.recv(
30
)
user_passwd_bytes
=
conn.recv(
30
)
user_name
=
user_name_bytes.decode(
'gbk'
)
user_passwd
=
user_passwd_bytes.decode(
'gbk'
)
with
open
(
'user.json'
,
'r'
, encoding
=
'utf-8'
) as f:
user_dict
=
json.loads(f.read())
if
user_name
in
user_dict
and
user_dict[user_name]
=
=
user_passwd:
conn.send(
'True'
.encode(
'utf-8'
))
print
(
"ftp连接成功"
)
ftp_load(conn, user_name)
#ftp上传下载实现
else
:
conn.send(
'False'
.encode(
'utf-8'
))
except
Exception:
conn.send(
'False'
.encode(
'utf-8'
))
conn.close()
ftp_obj.close()
|
本文转自小白的希望 51CTO博客,原文链接:http://blog.51cto.com/haoyonghui/1941026,如需转载请自行联系原作者