用sha256验证的python套接字文件传输不起作用,但有时只是?

时间:2018-01-17 20:25:36

标签: python sockets

客户方:

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()

因此,在我从计算机上运行的所有测试中,数据上传工作正常,甚至在通过我的移动连接上传数据时工作正常,但有时人们说它需要很长时间并且几分钟后就会将其杀死。数据存在于他们的计算机上但不存在于服务器上。我不知道发生了什么,请帮忙!

1 个答案:

答案 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()结果(包括计算大小的位置)。当客户端断开连接时就是这种情况。

不幸的是,在你面前有很多工作要做。你必须重写整个发送和接收代码。