我正在尝试实现一个UDP客户端程序,该程序通过发送多个读取请求并接收文件的小块作为回报(1400字节,以防止碎片)来从服务器接收文件。每次发送请求时,我都会设置一个select()调用,超时时间为1秒。如果我在该时间内收到响应,客户端将继续发送对下一段文件的请求。否则,客户端将重新发送对相同文件的请求。
这种顺序设计的问题是,客户端在发送下一个请求之前,要等待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 != "x00x00x00r":
self.recv_invalid_response(recv_data, "bit_signature")
continue
else:
if response_type == "x00x00x00x02":
#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
您想要实现的被称为"滑动窗口",就像TCP一样。这会很复杂,因为你需要考虑往返时间。它仍在发展中,看看不同操作系统的TCP实现如何具有不同的性能。也许你可以找到一些已经实现它的库
有没有理由不使用TCP?