Таймеры и повторные передачи в программе передачи файлов UDP (с использованием низкоуровневых сокетов) - PullRequest
0 голосов
/ 27 марта 2012

Я пытаюсь реализовать клиентскую программу UDP, которая получает файл с сервера, отправляя несколько запросов на чтение и получая небольшие части файла взамен (1400 байт, чтобы предотвратить фрагментацию). Каждый раз, когда я отправляю запрос, я настраивал вызов select () с таймаутом в 1 секунду. Если я получу ответ в течение этого времени, клиент отправит запрос на следующий фрагмент файла. В противном случае клиент повторно отправляет запрос на тот же фрагмент файла.

Проблема с этим последовательным дизайном заключается в том, что клиент ожидает ответа на КАЖДЫЙ запрос, прежде чем отправит следующий. Если есть даже небольшое соотношение потерь пакетов, это увеличит время, необходимое для отправки даже файла средней величины, до довольно неприемлемых уровней.

Я хотел бы спроектировать клиент так, чтобы он мог отправлять все запросы на чтение без ожидания ответов, одновременно выполняя цикл таймера и повторной передачи, который повторно отправляет отдельные запросы, которые не получают ответы. Тем не менее, я довольно новичок в программировании в целом, и не могу понять, как это сделать. Нужно ли открывать несколько сокетов одновременно и запускать разные циклы на каждом? Или есть более простой способ сделать это?

Мой текущий код (простите за беспорядок):

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 Ответ

1 голос
/ 27 апреля 2012

то, что вы хотите реализовать, называется «скользящим окном», как это делает TCP.Это будет сложно, потому что вам нужно учитывать время поездки туда и обратно.Это все еще развивается, посмотрите, как реализации TCP разных операционных систем имеют разные характеристики.Возможно, вы можете найти какую-то библиотеку, которая уже реализует это.

Есть ли причина не использовать TCP?

...