python - 我可以避免 Python 中的线程 UDP 套接字丢失数据吗?

标签 python multithreading sockets gtk pygtk

首先,我是 Python 的新手,在工作中学习,所以要温柔!

我正在尝试为 Windows 编写一个线程化的 Python 应用程序,它从 UDP 套接字 (thread-1) 读取数据,将其写入文件 (thread-2),并将实时数据 (thread-3) 显示到小部件(gtk.Image 使用 gtk.gdk.pixbuf)。我正在使用队列在线程之间传递数据。

我的问题是,如果我只启动线程 1 和线程 3(因此暂时跳过文件写入),似乎在前几个样本之后我丢失了一些数据。在这个下降之后它看起来很好。即使在运行线程 3 之前让线程 1 完成,这种明显的下降仍然存在。

对代码片段的长度表示歉意(我删除了写入文件的线程),但我觉得删除代码只会引发问题。希望有人可以阐明 :-)

import socket
import threading
import Queue
import numpy
import gtk
gtk.gdk.threads_init()
import gtk.glade
import pygtk


class readFromUDPSocket(threading.Thread):

    def __init__(self, socketUDP, readDataQueue, packetSize, numScans):
        threading.Thread.__init__(self)
        self.socketUDP = socketUDP
        self.readDataQueue = readDataQueue
        self.packetSize = packetSize
        self.numScans = numScans

    def run(self):
        for scan in range(1, self.numScans + 1):
            buffer = self.socketUDP.recv(self.packetSize)
            self.readDataQueue.put(buffer)
        self.socketUDP.close()
        print 'myServer finished!'


class displayWithGTK(threading.Thread):

    def __init__(self, displayDataQueue, image, viewArea):
        threading.Thread.__init__(self)
        self.displayDataQueue = displayDataQueue
        self.image = image
        self.viewWidth = viewArea[0]
        self.viewHeight = viewArea[1]
        self.displayData = numpy.zeros((self.viewHeight, self.viewWidth, 3), dtype=numpy.uint16)

    def run(self):
        scan = 0
        try:
            while True:
                if not scan % self.viewWidth: scan = 0
                buffer = self.displayDataQueue.get(timeout=0.1)
                self.displayData[:, scan, 0] = numpy.fromstring(buffer, dtype=numpy.uint16)
                self.displayData[:, scan, 1] = numpy.fromstring(buffer, dtype=numpy.uint16)
                self.displayData[:, scan, 2] = numpy.fromstring(buffer, dtype=numpy.uint16)
                gtk.gdk.threads_enter()
                self.myPixbuf = gtk.gdk.pixbuf_new_from_data(self.displayData.tostring(), gtk.gdk.COLORSPACE_RGB,
                                                        False, 8, self.viewWidth, self.viewHeight, self.viewWidth * 3)
                self.image.set_from_pixbuf(self.myPixbuf)
                self.image.show()
                gtk.gdk.threads_leave()
                scan += 1
        except Queue.Empty:
            print 'myDisplay finished!'
            pass


def quitGUI(obj):
    print 'Currently active threads: %s' % threading.enumerate()
    gtk.main_quit()


if __name__ == '__main__':

    # Create socket (IPv4 protocol, datagram (UDP)) and bind to address
    socketUDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    host = '192.168.1.5'
    port = 1024
    socketUDP.bind((host, port))

    # Data parameters
    samplesPerScan = 256
    packetsPerSecond = 1200
    packetSize = 512
    duration = 1  # For now, set a fixed duration to log data
    numScans = int(packetsPerSecond * duration)

    # Create array to store data
    data = numpy.zeros((samplesPerScan, numScans), dtype=numpy.uint16)

    # Create queue for displaying from
    readDataQueue = Queue.Queue(numScans)

    # Build GUI from Glade XML file
    builder = gtk.Builder()
    builder.add_from_file('GroundVue.glade')
    window = builder.get_object('mainwindow')
    window.connect('destroy', quitGUI)
    view = builder.get_object('viewport')
    image = gtk.Image()
    view.add(image)
    viewArea = (1200, samplesPerScan)

    # Instantiate & start threads
    myServer = readFromUDPSocket(socketUDP, readDataQueue, packetSize, numScans)
    myDisplay = displayWithGTK(readDataQueue, image, viewArea)

    myServer.start()
    myDisplay.start()

    gtk.gdk.threads_enter()
    gtk.main()
    gtk.gdk.threads_leave()
    print 'gtk.main finished!'

最佳答案

UDP 不验证目标是否接收到它(就像 TCP 一样)- 如果您想确保所有数据都到达,您必须在您的应用程序中实现重传等。您是否控制发送 UDP 源?

关于python - 我可以避免 Python 中的线程 UDP 套接字丢失数据吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2456727/

相关文章:

python - 如何在 Windows 上运行 celery?

c# - 使用异步 CTP 同时下载 HTML 页面

c# - StreamSocket、DataWriter.StoreAsync()、DataReader.LoadAsync() -- 异步问题

python - 如何修复 "W293 blank line contains whitespace"

python - 在 Excel 文件中禁用 protected View 模式 - 使用 xlwt 、 python

python - 如何用数值替换分类值?

iphone - iOS 应用未能及时启动 0x000000008badf00d - applicationDidBecomeActive 延迟

ios - 在可变数组访问上普遍使用@synchronized 指令的替代方法

c++ - 如何将本地端点绑定(bind)到套接字?

sockets - 将 net.Conn.Read 用于持久 TCP 套接字的正确方法是什么