TCP套接字文件传输
我想写一个安全的传输文件程序使用Python和AES,我有一个问题,我不完全明白。我通过使用1024字节的块来解析文件并发送它们,但接收数据的服务器端发生崩溃(我使用AES CBC,因此我的数据长度必须是16字节的倍数),并且我得到的错误表示它是不。TCP套接字文件传输
我试图打印客户端发送的数据的长度和客户端接收到的数据的长度,它表明客户端每次发送的时间恰好是它应该发送的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
欢迎来到网络编程!你刚刚陷入了同样的错误的假设,即大家第一次通过假设客户端发送&服务器recives应该是对称的。不幸的是,这种情况并非如此。操作系统允许接收发生在任意大小的块中。尽管这样做很容易,只是缓冲你的数据,直到你读入的数量等于你希望收到的数额。沿此线的东西就可以了:
buff=''
while len(buff) < 1024:
buff += s.recv(1024 - len(buff))
TCP是一种流协议,它不会像以前发现的那样节省消息边界。
什么TCP可以保证的是,所有的数据到达时,按照正确的顺序,在某些时候。 (除非意外发生,否则它不会到达。)但是,您发送的数据很可能仍会以大块的形式出现。其中很大一部分是因为发送缓冲区和接收缓冲区有限。你应该做的是继续做你的recv
调用,直到你有足够的数据来处理它。您可能需要多次拨打send
;使用它的返回值来跟踪到目前为止发送/缓冲了多少数据。
当你做print socket.SO_RCVBUF
,你居然打印符号SO_RCVBUF 含量的不同(除了Python并不真的有常数);用来告诉setsockopt
你想改变什么。要获得当前值,您应该拨打getsockopt
。
谢谢,这与Rakis的答案一起帮助很大。我试图将你的答案设置为Rakis的答案,但似乎我只能设置一个答案,这太糟糕了:( – Nolhian 2010-07-06 21:39:18
正如其他人指出,你可能正在处理一个不完整的消息。你需要有固定大小的消息或者有一个分隔符(不要忘记逃离你的数据!),这样你就知道何时收到完整的消息。
这是我前段时间编写的代码片段,可能不是最好的,但它可能是通过本地网络传输大文件的好例子。 http://setahost.com/sending-files-in-local-network-with-python/
与TCP无关(因为已经得到了回答),但是如果您期望收到很多,则重复附加到字符串将效率低下。最好追加到列表中,然后在使用''.join(list)
完成接收时将列表转换为字符串。
如上
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())
如果您将代码发布到recv()调用的周围,那么找出错误会更容易一些。假设你每次传输调用一次recv(),你应该知道你不能期望在一次调用recv()的时候获得你发送的所有数据的1024个字节。您需要循环调用recv()并连接到缓冲区,直到您收到您期望的1024个字节。 – Faisal 2010-07-06 20:19:56