You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
6.0 KiB
146 lines
6.0 KiB
from socket import *
|
|
import struct
|
|
import json
|
|
from RSA_Module import *
|
|
from Zip_Module import *
|
|
from AES import AESdecrypt
|
|
from PyQt5.QtCore import pyqtSignal, QObject
|
|
|
|
class TCPClient(QObject):
|
|
# 定义自定义信号
|
|
|
|
list_received = pyqtSignal(str)
|
|
receive_status = pyqtSignal(str) # 当发生错误时发出或者一些状态文件
|
|
receive_progress = pyqtSignal(int)
|
|
def __init__(self, buffsize=1024):
|
|
super().__init__()
|
|
self.buffsize = buffsize
|
|
self.tcp_client = socket(AF_INET, SOCK_STREAM)
|
|
self.connected = False
|
|
def connect(self, ip, port):
|
|
self.tcp_client.connect_ex((ip, port))
|
|
self.connected = True
|
|
generate_rsakey('clientpub.pem', 'clientpri.pem')
|
|
return self.tcp_client
|
|
def send_clientpub(self, client_conn):
|
|
filesize = os.path.getsize('./.tempfile/clientpub.pem')
|
|
newfilename = 'new_' + os.path.basename('./.tempfile/clientpub.pem')
|
|
dirc = {
|
|
'filename': newfilename,
|
|
'filesize': filesize,
|
|
}
|
|
head_info = json.dumps(dirc)
|
|
head_info_len = struct.pack('i', len(head_info))
|
|
client_conn.send(head_info_len)#发送head_info的长度
|
|
client_conn.send(head_info.encode('utf-8'))
|
|
|
|
#发送文件数据
|
|
with open('./.tempfile/clientpub.pem', 'rb') as f:
|
|
data = f.read()
|
|
client_conn.sendall(data)
|
|
|
|
|
|
def recv_serverpub(self, client_conn):
|
|
head_info_len = client_conn.recv(4)
|
|
head_info_len = struct.unpack('i',head_info_len)[0]
|
|
|
|
#接收并解析报头内容
|
|
head_info = client_conn.recv(head_info_len)
|
|
dirc = json.loads(head_info.decode('utf-8'))
|
|
filename = dirc['filename']
|
|
filesize = dirc['filesize']
|
|
received_size = 0
|
|
with open(f'./.tempfile/{filename}', 'wb') as f:
|
|
while received_size < filesize:
|
|
if filesize - received_size > self.buffsize:
|
|
data = client_conn.recv(self.buffsize)
|
|
f.write(data)
|
|
received_size += len(data)
|
|
else:
|
|
data = client_conn.recv(filesize - received_size)
|
|
f.write(data)
|
|
received_size += len(data)
|
|
if received_size == filesize:
|
|
return True, filename
|
|
else:
|
|
return False, filename
|
|
|
|
def receive(self, client_conn):
|
|
if not client_conn:
|
|
self.receive_status.emit("未连接到服务端")
|
|
return
|
|
try:
|
|
i = 1
|
|
while True:
|
|
head_info_len = client_conn.recv(4)
|
|
if head_info_len == 4:
|
|
self.receive_status.emit('正在接收文件中...')
|
|
head_info_len = struct.unpack('i', head_info_len)[0]
|
|
|
|
# 接收并解析报头内容
|
|
head_info = client_conn.recv(head_info_len)
|
|
dirc = json.loads(head_info.decode('utf-8'))
|
|
filename = dirc['filename']
|
|
filesize_bytes = dirc['filesize_bytes']
|
|
fileindex = dirc['fileindex']
|
|
ext = dirc['fileext']
|
|
lineEdit1 = '正在接收第' + str(i) + \
|
|
'号文件【' + filename + '】......'
|
|
self.list_received.emit(lineEdit1)
|
|
received_size = 0
|
|
with open(f'./.tempfile/{filename}', 'wb') as f:
|
|
while received_size < filesize_bytes:
|
|
if filesize_bytes - received_size > self.buffsize:
|
|
data = client_conn.recv(self.buffsize)
|
|
f.write(data)
|
|
received_size += len(data)
|
|
else:
|
|
data = client_conn.recv(filesize_bytes - received_size)
|
|
f.write(data)
|
|
received_size += len(data)
|
|
self.receive_progress.emit(int((received_size / filesize_bytes) * 100))
|
|
lineEdit2 = '成功接收第' + str(i) + \
|
|
'号文件【' + filename + '】 --> ' + \
|
|
os.getcwd() + '\\.tempfile\\' + filename
|
|
self.list_received.emit(lineEdit2)
|
|
if not self.sign_file(filename, ext): #发送签名状态
|
|
self.send_state(client_conn, i, False)
|
|
self.list_received.emit(f'第{i}号文件签名错误,重新接收...')
|
|
else:
|
|
self.send_state(client_conn, i, True)
|
|
self.list_received.emit(f'第{i}号文件签名验证成功')
|
|
i = i + 1
|
|
if fileindex == -1:
|
|
self.receive_status.emit('文件全部安全接收完成')
|
|
break
|
|
|
|
except Exception as e:
|
|
print(f'接收文件失败: {e}')
|
|
return
|
|
def sign_file(self, filename, ext):
|
|
unzip_file(f'./.tempfile/{filename}', './.tempfile')
|
|
aeskey = RSAdecrypt('./.tempfile/clientpri.pem', f'./.tempfile/{filename}_key')
|
|
decrypted_message = AESdecrypt(f'./.tempfile/{filename}{ext}', aeskey)
|
|
state = verify_signature(decrypted_message,'./.tempfile/new_serverpub.pem',f'./.tempfile/{filename}_sig')
|
|
if state:
|
|
with open(f'./.tempfile/{filename}{ext}', 'rb') as f :
|
|
data = f.read()
|
|
with open(f'./{filename}{ext}', 'wb') as s:
|
|
s.write(data)
|
|
|
|
return state
|
|
def send_state(self,client_conn, fileindex, state):
|
|
dirc = {
|
|
'fileindex': fileindex,
|
|
'state': state,
|
|
}
|
|
head_info = json.dumps(dirc)
|
|
head_info_len = struct.pack('i', len(head_info))
|
|
|
|
client_conn.send(head_info_len) # 发送head_info的长度
|
|
client_conn.send(head_info.encode('utf-8'))
|
|
|
|
|
|
|
|
|