所以我一直在使用Python的UDP服务器 - 客户端程序(如果它是相关的,使用Ubuntu)。现在,我已经实现了一种缓解数据包丢失的实现,主要是让客户端在服务器发送更多数据之前确认收到的数据包。在我试图加快这种转移的性能时,我开始不那么频繁地发送ACK(我最初在确认每个数据包)。在我的测试中,我发现无论出于何种原因,12个数据包都是我可以保证传送的最大数据包数量。我很好奇为什么12是"魔术数字"我的插座。
我在本地127.0.0.1网络上发送14000字节的数据包。 为了测试这是否是套接字可以接收多少字节的问题,我试图降低字节/数据包的数量,然后增加ACK数据包的数量。因此,如果14000 * 12 = 168000,我尝试了数据包大小和数据包数量的各种组合,总共168000字节。无论如何,12仍然是神奇的数字。
我也在其他计算机上对此进行了测试,以确保套接字缓冲区,MTU或其他系统相关变量不存在问题。
修改 我甚至在不同的程序中尝试过类似的过程。我一直在努力重写这个程序,但仍然保持中心思想(不太频繁的ACK)相同,并且12似乎仍然是"幸运"号。
我的代码如下:
客户端:
try:
while(dataChunk):
if(numRecv >= 12):
#print "Stuff"
sock.settimeout(.1)
tcp_sock.send("I got 12 packets")
count +=1
numRecv = 0
else:
actualNumChunks += 1
numRecv +=1
f.write(dataChunk)
sock.settimeout(.1)
dataChunk, addr = sock.recvfrom(buf)
packID, junkAddr = sock.recvfrom(buf)
packIDString = str(packID)
#tcp_sock.send(packIDString)
else:
print "Data no longer being recv"
except socket.timeout:
f.close()
sock.close()
服务器:
for chunk in read_in_chunks(f):
if(s.sendto(chunk,addr) and s.sendto(str(local_ID),addr)):
numSent += 1
'''
Store the packet being sent in the appropriate spot
Indices are arranged by packet localID, and each spot contains the packets load (as a string)
'''
packetQueue.insert(local_ID,chunk)
'''
Wait on ACK packets from the client
We will receive these packets over TCP (expecting the unique Packet ID/sequence number)
We won't send another packet until we've received the ACK from the client
If, after x seconds, we haven't received an ACK, we will assume packet was lost, and queue it for retransmission
'''
if(numSent >= 12):
conn.settimeout(.05)
try:
ACK = conn.recv(tcp_buf)
if ACK:
numSent = 0
else:
print "ACK is NONE!"
except socket.timeout:
ACK = None
print "Socket timed out (after "+str(count) +" loops) because we didn't get an ACK, let's send him some more packets"
#conn.settimeout(5)
while (ACK is not "I got 12 packets"):
"""
Continue with the main loop, and send more packets,
until we get something back (i.e. the client got another 12 packets)
"""
bigDataChunk = packetQueue[local_ID] + packetQueue[local_ID] + packetQueue[local_ID]
s.sendto(bigDataChunk, addr)
try:
ACK = conn.recv(tcp_buf)
print "He just ACKed the big ass data chunk: ",ACK
except socket.timeout:
print "Socket just timed out again..."
if ACK:
print "This is the ACK: ", ACK
break
else:
print "Need to send more packets yet"
else:
print "We got an ACK: " + ACK
'''
Compare this ACK (likely the packets received) against what we know we sent.
There is probably some discrepancy that will need to be addressed. That is to say, he is probably missing some
packets, and we're gonna have to resend them now, or make a list to send them later
'''
count += 1
numSent = 0
local_ID += 1
正如对任何可能得到答案的人的说明:我真的是出于好奇而要求。在实践中,我将不得不容忍一定程度的数据包丢失,然后重新传输丢失的数据报。然而,即使我确实允许一定数量的数据丢失,也只有少量传送12个数据包。这个程序是为大文件传输而设计的,我需要一致地获得超过12个数据包(尝试几千个),因为我不能一直要求重新发送数据包。
谢谢