title: Timers and retransmissions in a UDP file transfer program (using low-level sockets)
body: <p>I'm trying to implement a UDP client program that receives a file from the server by sending multiple read requests and receiving small pieces of the file in return (1400 bytes, to prevent fragmentation). Each time I send a request, I set up a select() call with a timeout of 1 second. If I receive a response within that time, the client goes on to send the request for the next piece of file. Otherwise, the client resends the request for the same piece of file.</p>
  
  <p>The problem with this sequential design is that the client waits for EACH request to be responded to before it sends the next one. If there is even a small ratio of packet losses, this would increase the time required for the sending of even a moderately large file to pretty unacceptable levels.</p>
  
  <p>I would like to design the client to be able to send all of the read requests without waiting for responses, while simultaneously running a timer and retransmission loop that resends the individual requests that do not receive responses. However, I'm pretty new to coding in general, and can't seem to figure out how to do that. Do I need to open up several sockets at a time and run different loops on each? Or is there a more straightforward way of doing it?</p>
  
  <p>My current code is (forgive the messiness):</p>
  
  <pre><code>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 &lt; 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 &gt;= 60):
          print ("Exceeded number of retransmissions allowed. Exiting program.")
          sys.exit()      
  
      return
  </code></pre>