我想通过UDP传输多个图像。我知道可以使用TCP,但我想通过UDP使用它。下面是我使用的代码片段。是否可以通过UDP传输更大的文件?我设法传输小文件,但对大文件失败。感谢使用UDP套接字的任何帮助或替代方法。
客户代码收到图片。
supports.svg
服务器端发送数据
BUF_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('localhost', port))
sock.settimeout(30)
def rcv_data(sock, num_packet_to_recv, file_size):
bytes_rcvd = bytearray()
f = open(download_dir , 'wb')
print('Receiving packets will start')
while num_packet_to_recv > 0:
try:
client_data, server_addr = sock.recvfrom(BUF_SIZE + 8)
seq_num = client_b_data[-8:]
img_data = client_data[:-8]
num_packet_to_recv = num_packet_to_recv - 1
#store img_data and seq_num to bytes_rcvd for later
#sorting by sequence number
f.write(sorted_bytes_rcvd)
except Exception as e:
print('rcv error {}'.format(e))
f.close()
答案 0 :(得分:2)
您发布的代码似乎假设从发送方到接收方的路由中不会丢弃任何数据包-这种假设在现实生活中不会成立(即使发送方和接收方处于两者都位于同一台机器上!),这很可能是导致您的传输无法执行的原因,除了很小的文件(您可以靠运气来确保所有数据包都能在第一次尝试中通过) )。
要实现更强大的机制,您的接收器程序将需要某种方式来(a)检测数据包何时被丢弃,并且(b)通过向发件人发送一条消息以请求发件人重新传输来对这一知识做出反应来自“丢失”数据包的数据。 (当然,重传请求包也可能会丢失,因此您还需要一种方法来处理它!)
与此同时,您的发送方程序不仅需要发送数据(如当前那样),还需要从接收方接收任何传入的重传请求数据包,并通过重传请求的数据来对它们作出反应。
根据协议的确切设计,发送方和接收方可能还需要在经过一定时间后不发送或接收数据的情况下采取措施,以避免在所有情况下都使文件传输过程停顿下来。接收本来会提前的数据包将被丢弃。
因此,您当前仅在循环中调用阻塞sendto()
或recvfrom()
的方法是不够的;相反,发送方和接收方都将需要实现某种状态机,以使它们都可以在适当的时间发送适当的数据包,并快速接收和处理任何传入的数据包。通常可以单独进行此操作发送方和接收方线程,或者将套接字设置为非阻塞模式,并在对select()
或poll()
的阻塞调用周围编写事件循环。 (我更喜欢后者,因为IMO虽然状态机很难解决,但多线程甚至更棘手)
将序列号放入每个数据包是一个好的开始;这样可以使接收器知道如何对数据进行排序,并使其能够检测到接收到的数据中是否有“空洞”。一旦检测到漏洞(即一个或多个丢失的序列号),便可以将数据包发送回发送方,要求重新发送这些数据包,而发送方将通过重新发送这些数据包来做出反应。根据需要重复操作,直到接收器收到具有每个可能序列号的数据包(您还需要以某种方式与接收器进行通信,以期望有多少个序列号)。