TCP套接字文件传输

4 投票
8 回答
9956 浏览
提问于 2025-04-16 00:54

我正在用Python和AES写一个安全的文件传输程序,但遇到了一些我不太明白的问题。我把文件分成1024字节的小块发送,但接收数据的服务器崩溃了(因为我使用的是AES CBC,所以我的数据长度必须是16字节的倍数),而且我收到的错误提示说数据长度不对。

我尝试在客户端打印发送的数据长度和服务器接收到的数据长度,结果显示客户端每次确实发送了1024字节,正如预期的那样,但服务器那边显示在某个时刻接收到的数据包长度不是1024字节(比如743字节)。

我尝试在客户端每次发送数据之间加上time.sleep(0.5),结果似乎有效。难道这可能是服务器端的socket缓冲区出现问题?是不是客户端发送的数据太快,导致服务器的socket缓冲区崩溃,数据因此被损坏或丢失,recv(1024)只接收到了一部分数据?这是我能想到的唯一原因,但这也可能完全不对,如果有人知道为什么会这样,那就太好了;)

根据我的想法,我尝试了:

    self.s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 32768000)
    print socket.SO_RCVBUF

我在服务器端设置了一个32MB的缓冲区,但在Windows XP上打印出来是4098,而在Linux上只显示8。我不知道该怎么理解这个,唯一知道的是似乎没有32MB的缓冲区,所以代码无法正常工作。

这篇帖子真长,希望你们有耐心看到这里!我完全迷失了,如果有人对此有任何想法,请分享一下 :D

感谢Faisal,我的代码在这里:

服务器端:(count是我的文件大小/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

8 个回答

2

正如其他人提到的,你可能正在处理一个不完整的信息。你需要要么使用固定大小的信息,要么使用一个分隔符(别忘了对你的数据进行转义!),这样你才能知道什么时候收到了完整的信息。

3

TCP是一种流协议,它不会保留消息的边界,就像你刚刚发现的那样。

8

欢迎来到网络编程的世界!你刚刚犯了一个大家第一次接触时都会有的误解,那就是认为客户端发送和服务器接收应该是对称的。其实并不是这样。操作系统允许接收数据的大小是可以变化的,可能会接收到不同大小的数据块。不过,这个问题其实很好解决,你只需要把数据缓冲起来,直到你读取的数据量和你想要接收的数据量相等。下面的代码可以帮你实现这个:

buff=''
while len(buff) < 1024:
    buff += s.recv( 1024 - len(buff) )

撰写回答