我正在尝试使用Python和AES编写一个安全的传输文件程序,我遇到了一个我不完全理解的问题。我发送我的文件通过解析1024字节块并发送它们但接收数据的服务器端崩溃(我使用AES CBC因此我的数据长度必须是16字节的倍数)并且我得到的错误说它是不
我尝试打印客户端客户端发送的数据长度和服务器上收到的数据长度,并显示客户端每次发送的字符数恰好为1024字节,但是服务器端显示,在某个时间点,接收的数据包不是,因此小于1024字节(例如743字节)。
我试图在客户端的每个套接字发送之间放一个time.sleep(0.5),它似乎工作。是否可能是服务器端的某种套接字缓冲区故障?太多的数据被客户端发送得太快,并且它在某种程度上破坏了服务器端的套接字缓冲区,因此数据被破坏或消失,而recv(1024)只收到一个破碎的块?这是我能想到的唯一的东西,但这也可能是完全错误的,如果有人知道为什么这不能正常工作会很好;)
按照我的想法尝试:
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 32768000)
print socket.SO_RCVBUF
我试图在服务器端放置32mbytes缓冲区,但在Windows XP上它在打印机上显示4098,在linux上它只显示8.我不知道我必须如何解释这一点,我唯一知道的是似乎它没有32mbytes缓冲区,所以代码不起作用。
嗯,这是一个非常长的帖子,我希望你们中的一些人有勇气把它全部读到这里!我完全迷失在那里如果有人对此有任何想法请分享:D
感谢费萨尔,我的代码在这里:
服务器端:(计数是我的文件大小/ 1024)
while 1:
txt=self.s.recv(1024)
if txt == " ":
break
txt = self.cipher.decrypt(txt)
if countbis == count:
txt = txt.rstrip()
tfile.write(txt)
countbis+=1
客户方:
while 1:
txt= tfile.read(1024)
if not txt:
self.s.send(" ")
break
txt += ' ' * (-len(txt) % 16)
txt = self.cipher.encrypt(txt)
self.s.send(txt)
提前致谢,
Nolhian
答案 0 :(得分:8)
欢迎使用网络编程!你只是陷入了错误的假设,即每个人第一次假设客户发送&服务器recives应该是对称的。不幸的是,这种情况并非如此。 OS允许接收以任意大小的块发生。这可以很方便地解决,只需缓冲您的数据,直到您读取的数量等于您希望接收的数量。根据这一点,可以解决这个问题:
buff=''
while len(buff) < 1024:
buff += s.recv( 1024 - len(buff) )
答案 1 :(得分:3)
TCP是一种流协议,它不像您刚刚发现的那样保留消息边界。
答案 2 :(得分:2)
正如其他人指出你可能正在处理一条不完整的消息。您需要具有固定大小的消息或具有分隔符(不要忘记转义数据!),以便您知道何时收到完整的消息。
答案 3 :(得分:1)
TCP可以保证的是,您的所有数据都以正确的顺序到达某个位置。 (除非发生意外情况,否则它将无法到达。)但是,您发送的数据很可能仍会以块的形式到达。其中很大一部分原因是发送和接收缓冲区有限。您应该做的是继续进行recv
调用,直到您有足够的数据来处理它。您可能需要多次致电send
;使用其返回值来跟踪到目前为止已发送/缓冲的数据量。
执行print socket.SO_RCVBUF
时,实际打印符号SO_RCVBUF 内容(除了Python实际上没有常量);过去常常告诉setsockopt
你要改变什么。要获取当前值,您应该调用getsockopt
。
答案 4 :(得分:1)
与TCP无关(因为已经回答过),但如果您希望收到很多内容,那么反复追加字符串效率会相当低。最好是附加到列表,然后在使用''.join(list)
完成接收后将列表转换为字符串。
答案 5 :(得分:0)
对于许多应用程序,Python的asynchat模块巧妙地抽象了TCP的复杂性。
答案 6 :(得分:0)
这是我前段时间写的很好的代码片段,可能不是最好的,但它可能是通过本地网络传输大文件的好例子。 http://setahost.com/sending-files-in-local-network-with-python/
答案 7 :(得分:0)
如上所述
TCP是一种流协议
您可以尝试使用此代码,其中数据是您的原始数据,您可以从文件或用户输入中读取它
发件人
import socket as s
sock = s.socket(s.AF_INET, s.SOCK_STREAM)
sock.connect((addr,5000))
sock.sendall(data)
finish = t.time()
接收机
import socket as s
sock = s.socket(s.AF_INET, s.SOCK_STREAM)
sock.setsockopt(s.SOL_SOCKET, s.SO_REUSEADDR, 1)
sock.bind(("", 5000))
sock.listen(1)
conn, _ = sock.accept()
pack = []
while True:
piece = conn.recv(8192)
if not piece:
break
pack.append(piece.decode())