支持动态更换IP和端口, 上传下载, 进度条显示, 正则校验文件格式, hash校验文件完整性
客户端
# coding=utf-8
from socket import *
import json
import struct
import os,re
import hashlib
ip = 0
port = 0
# 打印进度条
def progress(percent, symbol='█', width=40):
if percent > 1: # 超过 100% 的时候让其停在 1
percent = 1 # 可以避免进度条溢出
show_progress = ("▌%%-%ds▌" % width) % (int(percent * width) * symbol)
print("\r%s %.2f%%" % (show_progress, percent * 100), end='')
# hash 校验
def Hash_md5(file_path:str):
m = hashlib.md5()
m.update(str(os.path.getsize(file_path)).encode("utf-8"))
return m.hexdigest()
# 连接
def connection():
client = socket(AF_INET,SOCK_STREAM)
client.connect((ip,port))
return client
# 下载
def download(client):
client.send("1".encode("utf-8"))
while 1:
try:
file_path = input("Please enter the file path(q/exit)>>").strip()
if file_path.lower() == "q":break
if len(file_path) == 0:continue
to_path = input("Please enter the save directory(q/back)>>").strip()
if to_path.lower() == "q":continue
if not os.path.isdir(to_path):
print("not find");continue
else:
file_name = input("Please enter filename(q/back)>>").strip()
if file_name.lower() == "q":continue
if re.search(r'[/|:*"<>\\]',file_name):
print(r'Filenames cannot have these symbols:/|:*"<>\\');continue
goal_path = os.path.join(to_path,file_name)
client.send(file_path.encode("utf-8"))
bytes_4 = client.recv(4)
if bytes_4.decode("utf-8") == "4044":
print("not find");continue
else:
header_bytes_len = struct.unpack("i",bytes_4)[0]
header_bytes = client.recv(header_bytes_len)
header_dic = json.loads(header_bytes.decode("utf-8"))
date_len = header_dic["file_size"]
hash_md5 = header_dic["hash"]
recv_len = 0
with open(goal_path,"wb")as f:
while 1:
date = client.recv(1024)
recv_len += len(date)
percent = recv_len / date_len # 接收的比例
progress(percent, width=40) # 进度条的宽度40
f.write(date)
if recv_len == date_len: break
if hash_md5 == Hash_md5(goal_path): # hash 值校验
print("\nHash auth succeed\nFile saved...")
continue
else:
os.remove(goal_path) # 校验失败内容删除
print("Hash auth failed!!")
except Exception as E:
print(E);break
# 上传
def uploading(client):
client.send("2".encode("utf-8"))
while 1:
try:
file_path = input("Please enter the path of the uploaded file(q/exit)>>").strip()
if file_path.lower() == "q":break
file_path = os.path.normpath(file_path)
if not os.path.isfile(file_path):
print("not find");continue
goal_path = input("Please enter the destination path(q/back)>>").strip()
if goal_path.lower() == "q":continue
goal_path = os.path.normpath(goal_path)
client.send(goal_path.encode("utf-8"))
bytes_4 = client.recv(4)
if bytes_4.decode("utf-8") == "4044":
print("not find");continue
else:
file_name = input("Please name the new file(q/back)>>").strip()
if file_name.lower() == "q":continue
if re.search(r'[/|:*"<>\\]',file_name):
print(r'Filenames cannot have these symbols:/|:*"<>\\');continue
goal_file_path = os.path.join(goal_path,file_name)
file_size = os.path.getsize(file_path)
file_name = os.path.basename(file_path)
md5 = Hash_md5(file_path)
header_dic = {"file_name": file_name, "file_size": file_size, "hash": md5,"file_path":goal_file_path}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode("utf-8")
header_bytes_len = struct.pack("i", len(header_bytes))
client.send(header_bytes_len)
client.send(header_bytes)
send_len = 0
with open(file_path, "rb")as f:
for line in f:
send_len += len(line)
percent = send_len / file_size # 接收的比例
progress(percent, width=40) # 进度条的宽度40
client.send(line)
print("\nsuccessfully upload!")
except Exception as E:
print(E);break
func_dic = {
"1":["download ",download],
"2":["upload",uploading],
"3":["IP Settings",download],
}
# 连接服务端ip和端口并选择功能
def run():
while True:
print("Please enter the correct IP and port")
global ip,port
ip = input("Please enter IP(q/exit)>>").strip()
if ip.lower() == "q":break
port = input("Please enter PORT(q/exit)>>").strip()
if port.lower() == "q":break
if port.isdigit():
port = int(port)
else:
print("Please enter the number")
continue
try:
client = connection() # 检测连接是否建立成功
except Exception as E:
print(E);continue
while 1:
for k,v in func_dic.items():
print(f"{k} : {v[0]}")
select = input("Please select function>>")
if select == "3":break
if select in func_dic:
func_dic[select][1](client)
run()
服务端
# coding=utf-8
from socket import *
import json
import struct
import os,hashlib
# 绑定服务端地址
def connection():
server = socket(AF_INET,SOCK_STREAM)
server.bind((ip,port))
server.listen(5)
return server
# 建立连接选择功能
def recv_send(server):
while 1:
print("connection...")
conn,addr = server.accept()
print(f"from {addr} conn")
select = conn.recv(1)
if select.decode("utf-8") == "1":
download(conn)
elif select.decode("utf-8") == "2":
uploading(conn)
# 客户端下载
def download(conn):
while 1:
try:
file_path = conn.recv(1024)
file_path = os.path.normpath(file_path.decode("utf-8"))
if not os.path.isfile(file_path):
conn.send("4044".encode("utf-8"))
else:
file_size = os.path.getsize(file_path)
file_name = os.path.basename(file_path)
m = hashlib.md5()
m.update(str(file_size).encode("utf-8"))
md5 = m.hexdigest()
header_dic = {"file_name":file_name,"file_size":file_size,"hash":md5}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode("utf-8")
header_bytes_len = struct.pack("i",len(header_bytes))
conn.send(header_bytes_len)
conn.send(header_bytes)
with open(file_path,"rb")as f:
for line in f:
conn.send(line)
except Exception:
break
# 客户端的上传
def uploading(conn):
while 1:
try:
dir_path = conn.recv(1024)
dir_path = os.path.normpath(dir_path.decode("utf-8"))
if not os.path.isdir(dir_path):
conn.send("4044".encode("utf-8"));continue
else:
conn.send("4444".encode("utf-8"))
bytes_4 = conn.recv(4)
header_bytes_len = struct.unpack("i", bytes_4)[0]
header_bytes = conn.recv(header_bytes_len)
header_dic = json.loads(header_bytes.decode("utf-8"))
date_len = header_dic["file_size"]
goal_file_path = header_dic["file_path"]
recv_len = 0
with open(goal_file_path, "wb")as f:
while 1:
date = conn.recv(1024)
recv_len += len(date)
f.write(date)
if recv_len == date_len: break
continue
except Exception as E:
print(E);break
def run():
while True:
print("Please enter the correct IP and port")
global ip, port
ip = input("Please enter IP(q/exit)>>").strip()
if ip.lower() == "q": break
port = input("Please enter PORT(q/exit)>>").strip()
if port.lower() == "q": break
if port.isdigit():
port = int(port)
try:
server = connection()
except Exception as E:
print(E);continue
recv_send(server)
else:
print("Please enter the number")
continue
run()