如何获取以下代码将大文件分解为较小的部分并发送这些部分,而不是发送整个文件?它无法发送大文件(使用ubuntu iso测试大约600mb)
...some code
# file transfer
with open(sendFile, "rb") as f:
while 1:
fileData = f.read()
if fileData == "": break
# send file
s.sendall(EncodeAES(cipher, fileData))
f.close()
...more code
Run Code Online (Sandbox Code Playgroud)
我尝试使用f.read(1024),但这不起作用.
最后,在拆分文件时,我需要能够再次将这些部分放在一起.
我也在使用PyCrypto加密文件,如果这对我正在尝试做的事情有任何影响.猜猜加密单独的部分是最聪明的,而不是加密整个文件,然后将其分成几部分.
希望上面的代码足够了.如果没有,我将使用更多代码进行更新.
我可能错了,但我打赌你的实际问题并不是你想象的那样,而且你试图通过一次读取1K来解决问题也是没有用的.抱歉,如果我错了,你已经知道这些基本的东西了.
您正在尝试发送您的密文:
s.sendall(EncodeAES(cipher, fileData))
Run Code Online (Sandbox Code Playgroud)
在此代码中肯定没有长度信息,没有分隔符等.并且你不可能在这个函数之外发送长度数据,因为你不知道在获得这个代码之前密文会有多长.
所以,我猜对方正在做这样的事情:
data = s.recv(10*1024*1024)
with open(recvFile, "wb") as f:
f.write(DecodeAES(cipher, data))
Run Code Online (Sandbox Code Playgroud)
由于接收方无法知道加密文件的结束位置以及下一个加密文件(或其他消息)的开始,它所能做的就是尝试接收"所有内容",然后对其进行解密.但这可能是文件的一半,或文件加上6-1/2其他消息,或者某些先前消息的剩余部分加上文件的一半等.TCP套接字只是字节流,而不是单独消息的序列.如果要发送消息,则必须在TCP之上构建协议.
我猜你认为只有大文件失败的原因是你在localhost或简单的局域网上测试.在这种情况下,对于小sends来说,有99%的可能性recv与你发送的一样多.但是一旦你对其中一个缓冲区变得过大,它就会从99%的工作时间变为0%的时间,所以你认为问题在于你无法发送大文件.
你认为将它分成1024字节块的原因让你胡言乱语,这意味着你要快速连续地做一大堆消息,这使得发送和接收调用不太可能匹配到一个消息. -一.(或者这个可能更简单 - 例如,你没有匹配双方的变化,所以你不会像加密一样解密.)
每当您尝试通过网络发送任何类型的消息(文件,命令等)时,您都需要基于消息的协议.但TCP/IP是基于字节流的协议.那么,你如何处理呢?您在流协议之上构建消息协议.
最简单的方法是采用一个已经为您的目的而设计的协议,并且已经有客户端的Python库以及您可以直接用于服务器的Python库或库存守护程序.发送文件的一些明显示例是FTP,TFTP,SCP或HTTP.或者您可以使用通用协议,如netstring,JSON-RPC或HTTP.
如果您想学习自己设计和实现协议,有两种基本方法.
首先,您可以从Twisted,monocle,Tulip或其他一些框架开始,这些框架旨在完成所有繁琐且难以获取的工作,因此您只需编写您关注的部分:将字节转换为消息和消息成字节.
或者你可以自下而上,用基本的套接字调用(或asyncore类似的低级别的东西)构建你的协议处理程序.这是一个简单的例子:
def send_message(sock, msg):
length = len(msg)
if length >= (1 << 32):
raise ValueError('Sorry, {} is too big to fit in a 4GB message'.format(length))
sock.sendall(struct.pack('!I', length))
sock.sendall(msg)
def recv_bytes(sock, length):
buf = ''
while len(buf) < length:
received = sock.recv(4-len(buf))
if not received:
if not buf:
return buf
raise RuntimeError('Socket seems to have closed in mid-message')
buf += received
return buf
def recv_message(sock):
length_buf = recv_bytes(sock, 4)
length = struct.unpack('!I', buf)
msg_buf = recv_bytes(sock, length)
return msg_buf
Run Code Online (Sandbox Code Playgroud)
当然,在现实生活中,您不希望进行微小的4字节读取,这意味着您需要在多次调用recv_bytes时保存缓冲区.更重要的是,你通常要打开控制流周围,用Protocol或Decoder对象或回调或协程.你用字节来提供它,它用消息提供其他东西.(同样对于发送方,但这总是更简单.)通过从套接字中抽象出协议,您可以用完全不同的传输替换它 - 一个测试驱动程序(对于调试协议处理程序几乎必不可少),隧道协议,套接字连接到一个select反应器(同时处理多个连接)等.