客户方:
def send_file_to_hashed(data, tcpsock):
time.sleep(1)
f = data
flag = 0
i=0
tcpsock.send(hashlib.sha256(f.read()).hexdigest())
f.seek(0)
time.sleep(1)
l = f.read(BUFFER_SIZE-64)
while True:
while (l):
tcpsock.send(hashlib.sha256(l).hexdigest() + l)
time.sleep(1)
hashok = tcpsock.recv(6)
if hashok == "HASHOK":
l = f.read(BUFFER_SIZE-64)
flag = 1
if hashok == "BROKEN":
flag = 0
if not l:
time.sleep(1)
tcpsock.send("DONE")
break
return (tcpsock,flag)
def upload(filename):
flag = 0
while(flag == 0):
with open(os.getcwd()+'\\data\\'+ filename +'.csv', 'rU') as UL:
tuplol = send_file_to_hashed(UL ,send_to_sock(filename +".csv",send_to("upload",TCP_IP,TCP_PORT)))
(sock,flagn) = tuplol
flag = flagn
time.sleep(2)
sock.close()
服务器端:
elif(message == "upload"):
message = rec_OK(self.sock)
fis = os.getcwd()+'/data/'+ time.strftime("%H:%M_%d_%m_%Y") + "_" + message
f = open(fis , 'w')
latest = open(os.getcwd()+'/data/' + message , 'w')
time.sleep(1)
filehash = rec_OK(self.sock)
print("filehash:" + filehash)
while True:
time.sleep(1)
rawdata = self.sock.recv(BUFFER_SIZE)
log.write("rawdata :" + rawdata + "\n")
data = rawdata[64:]
dhash = rawdata[:64]
log.write("chash: " + dhash + "\n")
log.write("shash: " + hashlib.sha256(data).hexdigest() + "\n")
if dhash == hashlib.sha256(data).hexdigest():
f.write(data)
latest.write(data)
self.sock.send("HASHOK")
log.write("HASHOK\n" )
print"HASHOK"
else:
self.sock.send("HASHNO")
print "HASHNO"
log.write("HASHNO\n")
if rawdata == "DONE":
f.close()
f = open(fis , 'r')
if (hashlib.sha256(f.read()).hexdigest() == filehash):
print "ULDONE"
log.write("ULDONE")
f.close()
latest.close()
break
else:
self.sock.send("BROKEN")
print hashlib.sha256(f.read()).hexdigest()
log.write("BROKEN")
print filehash
print "BROKEN UL"
f.close()
因此,在我从计算机上运行的所有测试中,数据上传工作正常,甚至在通过我的移动连接上传数据时工作正常,但有时人们说它需要很长时间并且几分钟后就会将其杀死。数据存在于他们的计算机上但不存在于服务器上。我不知道发生了什么,请帮忙!
答案 0 :(得分:2)
首先:这与sha无关。
通过网络流式传输是不可预测的。这一行
rawdata = self.sock.recv(BUFFER_SIZE)
不保证您读取BUFFER_SIZE
个字节。在最坏的情况下,您可能只读取了1个字节。因此,由于假设rawdata包含整个消息,因此您的服务器端完全被破坏。情况更糟。如果客户端发送命令并快速散列,您可以获得rawdata == 'DONEa2daf78c44(...)
这是混合输出。
"悬挂"部分就是从那里开始的。跟踪你的代码,看看当服务器收到部分/破坏的消息时会发生什么(我已经在想象中做到了这一点:P)。
通过网络流式传输几乎从不像在一侧调用sock.send
而在另一侧调用sock.recv
。你需要一些缓冲/成帧协议。例如,您可以实现这个简单的协议:始终将前两个字节解释为传入消息的大小,如下所示:
客户端(伪代码)
# convert len of msg into two-byte array
# I am assuming the max size of msg is 65536
buf = bytearray([len(msg) & 255, len(msg) >> 8])
sock.sendall(buf)
sock.sendall(msg)
服务器(伪代码)
size = to_int(sock.recv(1))
size += to_int(sock.recv(1)) << 8
# You need two calls to recv since recv(2) can return 1 byte.
# (well, you can try recv(2) with `if` here to avoid additional
# syscall, not sure if worth it)
buffer = bytearray()
while size > 0:
tmp = sock.recv(size)
buffer += tmp
size -= len(tmp)
现在您已正确阅读buffer
变量中可以使用的数据。
警告:简化了服务器的伪代码。例如,您需要在任何地方检查空recv()
结果(包括计算大小的位置)。当客户端断开连接时就是这种情况。
不幸的是,在你面前有很多工作要做。你必须重写整个发送和接收代码。