UDP 读取丢失的数据包

问题描述 投票:0回答:1

我正在编写一个程序,除其他外,它可以通过 UDP 接收 GPS NMEA 语句。 当我接收数据时,我知道我丢失了数据包。 GPS 每秒发送 ZDA(时间)、VTG(航向和速度)、GGA(WGS84 位置)序列,如屏幕截图所示: GPS output

但是,在我编写的课程中,我丢失了数据包,但不明白为什么。 ZDA 每秒都受到热烈欢迎,但 VTG 和 GGA 电报则不然。这是我的输出:

['$GPZDA,204622.00,16,10,2023,,*63', '']
['$GPZDA,204623.00,16,10,2023,,*62', '']
['$GPZDA,204624.00,16,10,2023,,*65', '']
['$GPZDA,204625.00,16,10,2023,,*64', '']
['$GPZDA,204626.00,16,10,2023,,*67', '']
['$GPZDA,204627.00,16,10,2023,,*66', '']
['$GPZDA,204628.00,16,10,2023,,*69', '']
['$GPZDA,204629.00,16,10,2023,,*68', '']
['$GPZDA,204630.00,16,10,2023,,*60', '']
['$GPZDA,204631.00,16,10,2023,,*61', '']
['$GPZDA,204632.00,16,10,2023,,*62', '']
['$GPGGA,204632.00,2918.75039,N,09435.22487,W,5,26,0.6,33.64,M,-27.60,M,010,0481*53', '']
['$GPZDA,204633.00,16,10,2023,,*63', '']
['$GPZDA,204634.00,16,10,2023,,*64', '']
['$GPZDA,204635.00,16,10,2023,,*65', '']
['$GPZDA,204636.00,16,10,2023,,*66', '']
['$GPZDA,204637.00,16,10,2023,,*67', '']
['$GPZDA,204638.00,16,10,2023,,*68', '']
['$GPZDA,204639.00,16,10,2023,,*69', '']
['$GPZDA,204640.00,16,10,2023,,*67', '']
['$GPZDA,204641.00,16,10,2023,,*66', '']
['$GPZDA,204642.00,16,10,2023,,*65', '']
['$GNVTG,286.931,T,286.931,M,0.198,N,0.367,K,D*3A', '']
['$GPZDA,204643.00,16,10,2023,,*64', '']

我的UDP_socket类:


class UDP_socket(object):
    ''' mode = "utf8" or "binary" '''
    def __init__(self, host='', port=0, broadcast=True, mode='utf8'):
        self.host = host
        self.port = port
        self.broadcast = broadcast
        self.mode = mode
    
    def read(self):
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
            if self.broadcast:
                s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
            s.bind((self.host, self.port))
            if self.mode == 'binary':
                data = s.recv(1024).hex()
            else:
                data = s.recv(1024).decode('Utf8', 'replace').split('\r\n')
                print(data)
            return data

    def send(self, input, target):
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
            if self.broadcast:
                s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
            s.bind((self.host, self.port))
            s.sendto(input.encode('Utf8'), target)

来自我的 GPS 课程:


    def connect_socket(self):
        '''Create a socket UDP or TCP'''
        self.continuous_read = True
        self.button.configure(text="Disconnect", command=self.socket_stop)
        if self.tcpudp.get(): #0 for TCP
            # print(self.gps_address.get(), int(self.gps_port.get()))
            self.socket = UDP_socket(self.gps_address.get(), int(self.gps_port.get()), True)
        else:
            self.socket = TCP_socket(self.gps_address.get(), int(self.gps_port.get()) )
        self.gps_marker = Map_Marker(app.map, color = self.marker_color)
        readT = threading.Thread(target= lambda: self.socket_read(FALSE))
        readT.start()

    def socket_read(self, terminal):
        telegram = nmea_oi()
        while self.continuous_read:
            received_msg = self.socket.read()
            del received_msg[-1]
            for j in range(len(received_msg)):
                if telegram.decode(received_msg[j], 'All', terminal)[0] == 'GGA':
                    lat = telegram.decode(received_msg[j], 'All', terminal)[1][0]
                    long = telegram.decode(received_msg[j], 'All', terminal)[1][1]
                    self.gps_marker.update_marker(lat, long)
                self.update_displayed_lines(received_msg[j])

它可能看起来有点幼稚,但我对 python 和对象编程还很陌生。我尝试自己编写所有内容,进行实验和学习。除了那些丢失的数据包之外,一切都有效。

我尝试了不同的方法,例如将缓冲区大小增加到 2048。 我不使用任何延迟。通过使用软件可视化同一台计算机上收到的数据包,不会丢失电报。一定是我的代码... 可能是线程问题,还是某个时间问题?

我知道 UDP 并不可靠,但是,这是船上当前的设置。 GPS 数据通过 UDP 广播,所有使用此输出的软件都不会丢失任何数据包(我指的是 15 台以上的机器)。在许多这样的机器上,10 秒内没有 GGA 输入就会发出警报,但这种情况永远不会发生

任何想法将不胜感激。

python-3.x udp
1个回答
0
投票

确实如此!感谢您的帮助。

我修改了UDP类:

class UDP_socket(object):
    ''' mode = "utf8" or "binary" '''
    def __init__(self, host='', port=0, broadcast=True, mode='utf8'):
        self.host = host
        self.port = port
        self.broadcast = broadcast
        self.mode = mode
        self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        if self.broadcast:
            self.s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
            self.s.bind((self.host, self.port))

    def read(self):
        
        if self.mode == 'binary':
            data = self.s.recv(1024).hex()
        else:
            data = self.s.recv(1024).decode('Utf8', 'replace').split('\r\n')
            print(data)
        return data

    def send(self, input, target):
        self.s.sendto(input.encode('Utf8'), target)

    def close(self):
        self.s.close()
© www.soinside.com 2019 - 2024. All rights reserved.