UDP文件传输程序中的定时器和重新传输(使用低级套接字)

时间:2012-03-27 09:05:38

标签: python file sockets udp

我正在尝试实现一个UDP客户端程序,它通过发送多个读取请求并接收文件的一小部分(1400字节,以防止碎片)从服务器接收文件。每次发送请求时,我都会设置一个超时为1秒的select()调用。如果我在该时间内收到响应,则客户端继续发送下一个文件的请求。否则,客户端会重新发送同一文件的请求。

此顺序设计的问题是客户端在发送下一个请求之前等待EACH请求被响应。如果数据包丢失的比例很小,这会增加将中等大小的文件发送到相当不可接受的水平所需的时间。

我想将客户端设计为能够在不等待响应的情况下发送所有读取请求,同时运行定时器和重新发送循环,重新发送未接收响应的各个请求。但是,我对编码很新,而且似乎无法弄清楚如何做到这一点。我是否需要一次打开几个套接字并在每个套接字上运行不同的循环?或者有更简单的方法吗?

我目前的代码是(原谅混乱):

def read_service_loop(self):
    """Loop governing the timing, checking, and retransmission or processing of read service. """

    #Increment start_position each time packet sent, send a read request packet for each new position.
    #Expect to receive a read_response packet for each time read request sent.
    recv_data = None
    print("Sending request to server to read and receive file...")
    start_position = 0
    while(self.eof == False):

        print("Reading from byte " + str(start_position))       
        num_retransmits = 0

        #Loop for retransmissions of the same start position
        while(num_retransmits < 60):
        num_retransmits = num_retransmits + 1
        self.send_read_request(start_position)
        input_socket = [self.client_socket]
        inputready,outputready,exceptready = select.select(input_socket,[],[], 1)

        if (inputready == []):
            continue

        else:
            recv_data = self.client_socket.recv(self.buffer_)

            bit_signature = recv_data[0:4]
            response_type = recv_data[4:8]
            recv_payload = recv_data[8:]

            if bit_signature != "\x00\x00\x00\r":
            self.recv_invalid_response(recv_data, "bit_signature")
            continue
            else:
            if response_type == "\x00\x00\x00\x02":
                #Packet is valid, proceed to recv_read_response to append this bit of file received into local_filename
                self.file_append = open(self.local_filename, 'r+b')
                self.recv_read_response(recv_payload)
                break
            else:
                self.recv_invalid_response(recv_data, "response_type")
                continue

        start_position = start_position + self.NUM_BYTES_TO_READ

        if (num_retransmits >= 60):
        print ("Exceeded number of retransmissions allowed. Exiting program.")
        sys.exit()      

    return

1 个答案:

答案 0 :(得分:1)

您要实现的内容称为“滑动窗口”,就像TCP一样。这将很复杂,因为您需要考虑往返时间。它仍在不断发展,看看不同操作系统的TCP实现如何具有不同的性能。也许你可以找到一些已经实现它的库。

有什么理由不使用TCP?