Python文件传输(TCP套接字),网络缓慢问题

时间:2018-11-29 16:21:11

标签: python python-3.x tcp proxy file-transfer

我使用Tor和袜子设置了一个安全套接字,但是在发送大量数据时遇到了问题

发件人:

socket.send(message.encode())

收件人:

chunks = []

while 1:
    part = connection.recv(4096)
    chunks.append(part.decode())

    if len(part) < 4096:
        break

response = "".join(chunks)

由于循环中的网络速度不一致,所以我并不总是填充4096b缓冲区,所以循环中断了,我也没有收到完整的数据。

减小缓冲区的大小似乎不是一种选择,因为“数据包”的大小有时可以低至20b

3 个答案:

答案 0 :(得分:0)

TCP可以将程序包数据拆分为任意数量。因此,您从不永远不要将套接字的另一端依赖于接收到的数据包的大小。您必须发明另一种机制来检测消息结尾/文件结尾。

如果仅发送一个Blob并关闭套接字,则在服务器端只需读取,直到获得False值为止:

while True:
    data = sock.recv(1024)
    if data:
        print(data)
        # continue 
    else:
        sock.close()
        break

如果要发送多条消息,则必须决定它们之间的分隔符是什么。对于文本协议,最好使用行尾。然后,您可以享受Twisted LineReceiver协议和其他协议的强大功能。

如果您正在执行二进制协议,通常的做法是在每条消息的开头加上字节/字/双字大小。

答案 1 :(得分:0)

尝试使用结构将传入数据的长度首先传递给接收器“导入结构”。这样,接收端便确切知道要接收多少数据。在此示例中,字节是通过套接字发送的,这里的示例是我从github上传github.com/nsk89/netcrypt借来的示例,以供参考,并从send函数以及发送序列化字典中切出了加密步骤。

编辑我还应该澄清一下,当您通过套接字发送数据时,尤其是当您发送多条消息时,它们都作为一条长消息而位于流中。并非每条消息的长度都为4096字节。如果一个长度为2048,下一个为4096,则在缓冲区上收到4096时,您将收到第一条消息以及下一条消息的一半,或者完全挂起,等待更多不存在的数据。

data_to_send = struct.pack('>I', len(data_to_send)) + data_to_send # pack the length of data in the first four bytes of data stream, >I indicates internet byte order

    socket_object.sendall(data_to_send)  # transport data



def recv_message(socket_object):
    raw_msg_length = recv_all(socket_object, 4)  # receive first 4 bytes of data in stream
    if not raw_msg_length:
        return None

    # unpack first 4 bytes using network byte order to retrieve incoming message length
    msg_length = struct.unpack('>I', raw_msg_length)[0]

    return recv_all(socket_object, msg_length)  # recv rest of stream up to message length

def recv_all(socket_object, num_bytes):
    data = b''
    while len(data) < num_bytes:  # while amount of data recv is less than message length passed
        packet = socket_object.recv(num_bytes - len(data))  # recv remaining bytes/message
        if not packet:
            return None
        data += packet
    return data

答案 2 :(得分:0)

顺便说一句,在将它们组合成一个块之前,无需解码每个部分,将所有部分组合成一个块,然后解码该块即可。

针对您的情况,更好的方法是使用2个步骤。

第一步:发送方发送消息的大小,接收方采用此大小并准备接收消息。

步骤2:发送方发送消息,接收方根据需要合并数据。

发件人

# Step 1
socket.send( str(len(message.encode())).encode() ) 
# Step 2
socket.send(message.encode("utf-8"))   

接收器

# Step 1
message_size = connection.recv(1024) 
print("Will receive message size:",message_size.decode())

# Step 2
recevied_size  = 0 
recevied_data = b''
  while recevied_size < int(message_size.decode()):
      part = connection.recv(1024)
      recevied_size += len(part)
      recevied_data += part
  else:
      print(recevied_data.decode("utf-8", "ignore"))
      print("message receive done ....",recevied_size)