python-3.x UDP读取丢失的数据包

krugob8w  于 2023-10-21  发布在  Python
关注(0)|答案(1)|浏览(128)

我正在写一个程序,其中,除其他外,可以通过UDP接收GPS NMEA句子。当我接收数据时,我知道我丢失了数据包。GPS每秒发送一个ZDA(时间),VTG(课程和速度),GGA(WGS 84位置)的序列,如屏幕截图: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输入会发出警报,这种情况从未发生过
任何想法将不胜感激。

xzabzqsa

xzabzqsa1#

是啊!谢谢您的帮助。
我修改了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()

相关问题