4

我正在尝试使用 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

我试图在服务器端放置一个 32 兆字节的缓冲区,但在 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)

提前致谢,

诺利安

4

8 回答 8

8

欢迎来到网络编程!您刚刚陷入了同样的错误假设,即每个人第一次都假设客户端发送和服务器接收应该是对称的。不幸的是,这种情况并非如此。操作系统允许以任意大小的块进行接收。不过,这很容易解决,只需缓冲您的数据,直到您读取的数量等于您希望接收的数量。类似这样的东西可以解决问题:

buff=''
while len(buff) < 1024:
    buff += s.recv( 1024 - len(buff) )
于 2010-07-06T20:24:51.627 回答
3

TCP 是一种流协议,它不保留消息边界,正如您刚刚发现的那样。

于 2010-07-06T20:19:43.033 回答
2

正如其他人指出的那样,您可能正在处理不完整的消息。您需要有固定大小的消息或有一个分隔符(不要忘记转义您的数据!),以便您知道何时收到完整的消息。

于 2010-07-06T20:32:57.327 回答
1

TCP 可以保证的是,您的所有数据都会以正确的顺序到达某个时间点。(除非发生意外情况,否则它不会到达。)但是您发送的数据很可能仍会以块的形式到达。很大程度上是因为发送和接收缓冲区有限。您应该做的是继续进行recv呼叫,直到您有足够的数据来处理它。您可能需要send多次调用;使用它的返回值来跟踪到目前为止已经发送/缓冲了多少数据。

当你这样做时print socket.SO_RCVBUF,你实际上打印了符号 SO_RCVBUF常量(除了 Python 并没有真正的常量);用于告诉setsockopt您要更改的内容。要获取当前值,您应该改为调用getsockopt.

于 2010-07-06T20:27:03.750 回答
1

与 TCP 无关(正如已经回答的那样),但是如果您期望收到很多,重复附加到字符串将是相当低效的。最好附加到一个列表,然后在完成接收后使用''.join(list).

于 2011-11-08T15:14:00.097 回答
0

对于许多应用程序,TCP 的复杂性被 Python 的asynchat模块巧妙地抽象出来。

于 2010-07-06T21:41:30.910 回答
0

这是我前段时间写的一段漂亮的代码,可能不是最好的,但它可能是通过本地网络传输大文件的好例子。http://setahost.com/sending-files-in-local-network-with-python/

于 2011-10-31T20:30:23.913 回答
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())
于 2015-12-18T15:16:38.387 回答