qt udp多线程收发过程_使用 Qt 获取 UDP 数据并显示成图片

本文介绍了如何使用 Qt 在多线程环境下接收 UDP 数据包,解析包含RGB通道像素值的图像数据,并在窗口中显示。通过Python模拟发送数据,Qt客户端接收并处理,以应对高频率的数据流。文章还详细描述了自定义UDP包结构,并展示了如何在Qt中构建接收和处理数据的类结构,以及避免内存问题的技巧,如使用对象池减少new操作。
摘要由CSDN通过智能技术生成

一个项目,要接收 UDP 数据包,解析并获取其中的数据,主要根据解析出来的行号和序号将数据拼接起来,然后将拼接起来的数据(最重要的数据是 R、G、B 三个通道的像素值)显示在窗口中。考虑到每秒钟要接收的数据包的数量较大,Python 的处理速度可能没有那么快,而且之前对 Qt 也比较熟悉了,所以用Qt 作为客户端接收处理数据包,用近期学习的 Python 模拟发送数据包。

数据格式

在 TCP/IP 协议中,UDP 数据包的大小是由限制的,因此用 UDP 传输数据时,还要在 UDP 层上再封装一层自定义的协议。这个自定义的协议比较简单,每个 UDP 包的大小为 1432 个字节,分为几个部分:

部分

起始字节

字节长度

说明

Start

0

4

包头部的 Magic Number,设为 0x53746172

PartialCnt

4

1

分包总数,一个字节(0-255)以内

PartialIdx

5

1

分包序号

SampleLine

6

1

采样率

RGB

7

1

rgb 通道标识符

LineIdx

8

4

行号,每一行可以包含 RGB 三个通道的数据,每个通道由多个分包组成

ValidDataLen

12

4

数据部分有效字节数

LineBytes

16

4

每行数据包含的字节总数

Reserve

20

128

保留部分

Data

148

1280

数据部分

end

1428

4

包尾部的 Magic Number,设为 0x54456e64

上述表格描述的就是一个完整的 UDP 包。这里的一个 UDP 数据包包含的是 RGB 某个通道的某一部分的数据。换种说法:

一行数据

R 通道数据(若干个分包组成)

G 通道数据(若干个分包组成)

B 通道数据(若干个分包组成)

所以要生成/解析 UDP 包,最重要的是 PartialCnt、PartialIdx、RGB、LineIdx、Data 这几个部分。清楚了自定义协议就可以开始编写模拟包的生成和相应的接收逻辑了。

使用 Python 模拟 UDP 发包

由于本地开发的时候缺少必要的硬件环境,为了方便开发,用 Python 编写一个简单的 UDPServer,发送模拟生成的数据包。根据上述协议,可以写出如下的 CameraData 类来表示 UDP 数据包:

# -*- coding: utf-8 -*-

DATA_START_MAGIC = bytearray(4)

DATA_START_MAGIC[0] = 0x53 # S

DATA_START_MAGIC[1] = 0x74 # t

DATA_START_MAGIC[2] = 0x61 # a

DATA_START_MAGIC[3] = 0x72 # r

DATA_END_MAGIC = bytearray(4)

DATA_END_MAGIC[0] = 0x54 # T

DATA_END_MAGIC[1] = 0x45 # E

DATA_END_MAGIC[2] = 0x6e # n

DATA_END_MAGIC[3] = 0x64 # d

slice_start_magic = slice(0, 4)

slice_partial_cnt = 4

slice_partial_idx = 5

slice_sample_line = 6

slice_rgb_extern = 7

slice_line_idx = slice(8, 12)

slice_valid_data_len = slice(12, 16)

slice_line_bytes = slice(16, 20)

slice_resv = slice(20, 148)

slice_data = slice(148, 1428)

slice_end_magic = slice(1428, 1432)

import numpy as np

class CameraData(object):

def __init__(self):

# self.new()

# self.rawdata = rawdata

self.dataLow = 10

self.dataHigh = 20

self.new()

def genRandomByte(self, by=4):

r = bytearray(by)

for i in range(by):

r[i] = np.random.randint(0, 255)

def setPackageIdx(self, i = 0):

self.rawdata[slice_partial_idx] = i

def setRGB(self, c = 1):

self.rawdata[slice_rgb_extern] = c

def setLineIdx(self, line):

start = slice_line_idx.start

self.rawdata[start+3] = 0x000000ff & line

self.rawdata[start+2] = (0x0000ff00 & line) >> 8

self.rawdata[start+1] = (0x00ff0000 & line) >> 16

self.rawdata[start+0] = (0xff000000 & line) >> 24

def setValidDataLen(self, len):

start = slice_valid_data_len.start

Qt中,我们可以使用多线程来进行UDP收发操作。以下是一个简单的示例: 首先,我们需要创建一个UDP接收线程和一个UDP发送线程。 UDP接收线程可以继承自QThread类,并重写其run()函数。在run()函数中,我们可以创建一个QUdpSocket对象,并使用bind()函数将其与指定的IP地址和端口号进行绑定。然后,我们可以使用readyRead()信号来检测是否有新的数据到达。一旦有新的数据到达,我们可以使用receiveDatagram()函数来接收数据,并通过信号和槽机制将数据传递给主线程进行处理。 UDP发送线程也可以继承自QThread类,并重写其run()函数。在run()函数中,我们可以创建一个QUdpSocket对象,并使用writeDatagram()函数来发送数据。 在主线程中,我们需要创建一个UDP接收线程的实例和一个UDP发送线程的实例,并将其启动。然后,我们可以通过信号和槽机制将接收到的数据传递给其他需要处理该数据的部分。 需要注意的是,在使用多线程进行UDP收发操作时,我们需要保持数据的同步和线程安全。可以使用互斥锁(QMutex)来控制多个线程对共享资源的访问。 总结起来,使用多线程进行UDP收发操作需要创建UDP接收线程和UDP发送线程,并在主线程中进行线程的管理和数据的处理。通过合理使用信号和槽机制以及互斥锁,可以实现线程间的数据传输和同步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值