Python Socket接收大量的数据

当我尝试接收大量的数据时,它会被切断,我必须按回车才能获得其余的数据。 起初,我能够增加一点,但它仍然不会收到全部。 正如你所看到的,我已经增加了conn.recv()的缓冲区,但是它仍然没有得到所有的数据。 它在某个点上切断它。 我必须在我的raw_input上按回车才能接收其余的数据。 无论如何,我可以一次获得所有的数据吗? 这是代码。

port = 7777 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('0.0.0.0', port)) sock.listen(1) print ("Listening on port: "+str(port)) while 1: conn, sock_addr = sock.accept() print "accepted connection from", sock_addr while 1: command = raw_input('shell> ') conn.send(command) data = conn.recv(8000) if not data: break print data, conn.close() 

TCP / IP是基于stream的协议,而不是基于消息的协议。 无法保证每个peer send()调用都会导致另一个peer收到发送的确切数据的单个recv()调用 – 由于数据包的原因,它可能会接收到多个recv()碎片。

您需要在TCP之上定义自己的基于消息的协议,以区分消息边界。 然后,要阅读一条消息,继续调用recv()直到读完整条消息或发生错误。

发送消息的一个简单方法是以每个消息的长度作为前缀。 然后读一条消息,你首先读取长度,然后读取那么多字节。 你可以这样做:

 def send_msg(sock, msg): # Prefix each message with a 4-byte length (network byte order) msg = struct.pack('>I', len(msg)) + msg sock.sendall(msg) def recv_msg(sock): # Read message length and unpack it into an integer raw_msglen = recvall(sock, 4) if not raw_msglen: return None msglen = struct.unpack('>I', raw_msglen)[0] # Read the message data return recvall(sock, msglen) def recvall(sock, n): # Helper function to recv n bytes or return None if EOF is hit data = b'' while len(data) < n: packet = sock.recv(n - len(data)) if not packet: return None data += packet return data 

然后你可以使用send_msgrecv_msg函数来发送和接收整个消息,并且在networking级别上拆分或合并的数据包不会有任何问题。

你可以使用它: data = recvall(sock)

 def recvall(sock): BUFF_SIZE = 4096 # 4 KiB data = "" while True: part = sock.recv(BUFF_SIZE) data += part if part < BUFF_SIZE: # either 0 or end of data break return data 

您可能需要多次调用conn.recv()来接收所有的数据。 由于TCPstream不保留帧边界(即,它们只能用作原始字节stream而不是结构化的消息stream),所以不能保证一次调用所有数据, 。

看到这个答案的另一个问题的描述。

请注意,这意味着您需要知道何时收到所有数据。 如果发送方总是发送8000个字节,那么可以统计到目前为止收到的字节数,然后从8000中减去这个字节数,知道剩下多less个字节; 如果数据是可变大小的,还有其他各种可以使用的方法,比如让发送者在发送消息之前发送多个字节头,或者如果是正在发送的ASCII文本,则可以查找换行符或NUL字符。

被接受的答案是好的,但是对于大文件来说会很慢–string是不可变的类,这意味着每次使用+符号时都会创build更多的对象,使用list作为堆栈结构会更有效率。

这应该会更好

 while True: chunck = s.recv(10000) if not chunck: break fragments.append(chunck) print "".join(fragments) 

使用生成器函数(我认为更pythonic)的变化:

 def recvall(sock, buffer_size=4096): buf = sock.recv(buffer_size) while buf: yield buf if len(buf) < buffer_size: break buf = sock.recv(buffer_size) # ... with socket.create_connection((host, port)) as sock: sock.sendall(command) response = b''.join(recvall(sock)) 

修改Adam Rosenfield的代码:

 import sys def send_msg(sock, msg): size_of_package = sys.getsizeof(msg) package = str(size_of_package)+":"+ msg #Create our package size,":",message sock.sendall(package) def recv_msg(sock): try: header = sock.recv(2)#Magic, small number to begin with. while ":" not in header: header += sock.recv(2) #Keep looping, picking up two bytes each time size_of_package, separator, message_fragment = header.partition(":") message = sock.recv(int(size_of_package)) full_message = message_fragment + message return full_message except OverflowError: return "OverflowError." except: print "Unexpected error:", sys.exc_info()[0] raise 

然而,我会大力鼓励使用原来的方法。