Can I avoid a streaming UDP socket when deleting Python data?

First off, I'm new to Python and studied at work, so be gentle!

I am trying to write a Python Python streaming application for Windows that reads data from a UDP socket (stream-1), writes it to a file (stream-2) and maps the current data (stream-3) to a widget (gtk.Image using gtk.gdk .pixbuf). I use queues to exchange data between threads.

My problem is that if I only run threads 1 and 3 (so skip writing the file now), it seems that I lost some data after the first few samples. After this fall, everything looks great. Even if you let thread 1 finish before starting thread 3, this apparent drop still exists.

Sorry for the length of the code snippet (I deleted the stream that writes to the file), but I felt that deleting the code would just raise questions. Hope someone can shed some light :-)

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!'

+3
source share
5 answers

UDP does not check the purpose it receives (for example, TCP) - you must implement retransmission in your applications if you want all the data to arrive. Do you control the sending of the UDP source?

+4
source

UDP is by definition unreliable. You should not write programs that expect UDP datagrams to always pass.

TCP, , TCP ; TCP . , , ABCD, "A" "B" "C" "D" . , : "ABC", "D" "AB", CD " .. " ABC ", .

TCP "", , break; , , , , ​​ . .

UDP . UDP-: "AB", "CD", "EF" "GH", , , . . , UDP , , "ABCD" , .

: Python, GTK. , : .

, Twisted, API- listenUDP, GTK: datagramReceived, : UDP , . , TCP .

+2

- /, , , , :)

, , python per-se.

recv, UDP-. listen accept , , recv , , . .

, , , , , , recv packetSize , isn 't , recv .

, , , ? ""? , ?

, wireshark, , . , recv.


, , , . :

, , , recv, , .

, - , -- .

Queue.put .

, , 1200 , readFromUDPSocket, Queue.put, .

, recv , - , . , Queue, N- Queue, put 12 .

, 1200 , , , .

-1

-; recv ? , , UDP .

-, -, recv ( , ).

-; , ; recv ?

; , , , U UDP...

-1

, . :

  • Wireshark 1200 . , , . , - , .

  • , 15 . , recv 20 readFromUDPSocket, , .

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
        for i in range(0, 20):
            buffer = self.socketUDP.recv(self.packetSize)

    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!'

, ? , recv , .

-1

Source: https://habr.com/ru/post/1737195/


All Articles