确保通过Python中的UDP套接字接收所有数据

时间:2014-08-19 01:50:30

标签: python sockets networking udp

可能相关的问题似乎很接近,但没有像我理解的那样描述我的问题:

问题

逐行发送的长文件不会一直通过UDP over loopback。

长篇故事

我有一个由行和中断组成的长文件,与我在本地通过UDP从另一个程序获得的文件相同。我要强调的是,发送数据包的程序将通过UDP进行(这里没有选择),并且在发送时无法对可靠的处理ACK请求等进行修改。

看起来像这样(这是尾巴):

StimulusTime 56398

Signal(0,2) -79.5457

Signal(0,4) -81.7426

Signal(0,6) -83.9978

Signal(0,9) -63.3755

Signal(0,11) -15.6045

Signal(0,13) 31.1299

Signal(0,16) 75.7539

Signal(0,18) 98.301

Signal(0,20) 98.301

Signal(0,22) 48.4546

Signal(0,25) 3.73159

Signal(0,27) -49.9798

Signal(0,29) -77.8449

Signal(1,0) -22.0332

Signal(1,2) -60.6384

Signal(1,4) -98.0858

Signal(1,6) -86.4579

Signal(1,9) -68.9173

Signal(1,11) -31.5552

Signal(1,13) 35.2906

Signal(1,16) 77.0686

Signal(1,18) 96.3836

Signal(1,20) 95.7246

Signal(1,23) 25.6074

Signal(1,25) -20.2101

Signal(1,27) -60.2933

Signal(1,29) -83.8169

Signal(2,0) -31.8826

Signal(2,2) -53.5045

Signal(2,4) -89.9895

Signal(2,7) -84.4503

Signal(2,9) -59.7016

Signal(2,11) -12.8569

Signal(2,13) 28.857

Signal(2,15) 58.0577

Signal(2,18) 96.4222

Signal(2,20) 79.783

Signal(2,22) 58.6463

Signal(2,25) -3.24883

Signal(2,27) -45.5

Signal(2,29) -88.8937

Signal(3,0) -18.6625

Signal(3,2) -53.3978

Signal(1,16) 58.784

Signal(1,17) 44.7782

Signal(1,18) 6.247

Signal(1,19) -12.0855

Signal(1,20) -33.7644

Signal(1,21) -49.4406

Signal(1,22) -67.5791

Signal(1,23) -92.0336

Signal(1,24) -93.9841

END

我编写的代码接收此文件,并在本地通过UDP在本地发送一行,然后是接收它的代码,并根据数据类型对其进行解析。

发信人:

import socket
import sys

# Sends udp test data piped in from STDIN to the listener.
# ex: cat sampleoutput.txt | python testsender.py 

UDP_IP = "127.0.0.1"
UDP_PORT = 5000

print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP

# Send from stdin
if len(sys.argv) < 2:
  while True:
    line = sys.stdin.readline()
    if line:
      sock.sendto(line, (UDP_IP, UDP_PORT))
    else:
      break

  # get from file arg
else:
  myfile = open(str(sys.argv[1]), "r")
  while True:
    line = myfile.readline()
    if line:
      sock.sendto(line, (UDP_IP, UDP_PORT))
    else:
      break


sock.close()

监听器:

import socket
from array import array

UDP_IP = "127.0.0.1"
UDP_PORT = 5000

sock = socket.socket(socket.AF_INET,  # Internet
                     socket.SOCK_DGRAM)  # UDP
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024)  # buffer size arg

    print data
    # write to file for later testing
    # file = open("testdummy.txt", "a")
    # file.write(data)
    if data == "END\n":
        break

我能够使用上面的监听器从原始程序生成测试文件,因此它应该可以工作。不幸的是,正如tail -n 500 testdummy.txt | python testsender.py测试的那样,它有大约500行有效载荷失败,尽管它有点随机。具体来说,侦听器在发件人退出之前不会收到所有已发送的行,使其挂起,等待"END\n"字符串。

据我了解,套接字已处于阻塞模式 - 如何防止这种情况发生?

1 个答案:

答案 0 :(得分:0)

我的第一个建议是,如果你想传输保留了一系列行的文件,请不要使用UDP,如果你不想编写很多代码,请使用TCP。原因是;

  1. UDP是一种不可靠的协议,在某种意义上,收件人无法保证收到的数据包。
  2. UDP并不保证接收的数据包序列,这是因为UDP数据包可能通过多条路由(计算机之间的跳数)传递给接收方。因此,后面发送的数据包可以采用短路径并在之前发送的数据包之前到达接收方。 (&#34;结束\ n&#34;数据包可以在其他数据包之前)
  3. 另一方面,TCP是可靠的,并且保证了接收的数据包序列。非常适合文件传输。

    但不要担心像Bear Share这样的文件共享应用程序,Bit Torrents会使用UDP,但是你需要做一些额外的编码。

    1. 您需要实现一个确认协议,因为您需要为发送给收件人的每个数据包都有一个唯一的ID,并且当收到数据包时,收件人应该将一个确认数据包发送回发送方,并使用该ID来说明数据包收到了。
    2. 如果数据包丢失并且没有到达收件人(收件人没有确认),您必须再次(再次)重新发送数据包,直到您收到确认。
    3. 您可以通过不发送下一个数据包来控制订单,直到您获得前一个数据包的确认。