使用 Qt 通过蓝牙发送多个原始数据包
Sending multiple raw packet over Bluetooth with Qt
我编写了这段Python代码(使用pybluez)来通过L2CAP发送原始BNEP蓝牙数据包。目的是做一些类似模糊测试的测试。
BNEP_PSM = 0x000F
btSock = bluetooth.BluetoothSocket(bluetooth.L2CAP)
btSock.connect(('<some BDADDR>', BNEP_PSM))
for i in range(10):
btSock.send('<some payload>')
这工作得很好,并且正如预期的那样创建多个 BNEP 数据包,即使有效负载格式不正确。
现在,我正在尝试使用 Qt 在 C++ 中编写相同的函数,但它的工作方式不同。代码摘录如下:
QBluetoothSocket btSock(QBluetoothServiceInfo::L2capProtocol);
btSock.connectToService(QBluetoothAddress("<some BDADDR>"), QBluetoothUuid::Bnep);
QObject::connect(&btSock, &QBluetoothSocket::connected, [&btSock](){
int i = 10;
while (i--)
btSock.write("<some payload>");
});
使用i = 1
运行它可以很好地发送具有指定有效负载的单个数据包。 使用i = 10
运行它将导致单个数据包,其有效负载等于指定有效负载的十倍。
例如,在循环 3 中设置有效负载"AAAA"将导致在 Python 中使用第一种情况
+------------+----+ +------------+----+ +------------+----+
|L2CAP Header|AAAA| --> |L2CAP Header|AAAA| --> |L2CAP Header|AAAA|
+------------+----+ +------------+----+ +------------+----+
在第二种情况下,使用 Qt
+------------+------------+
|L2CAP Header|AAAAAAAAAAAA|
+------------+------------+
我怎样才能强制Qt套接字的write
表现得像Python套接字的send
?
更新:
查看文档,它说
当控制返回到事件循环时写入字节
如何在返回到事件循环之前强制刷新缓冲区?
如何在返回事件循环之前强制刷新缓冲区?
您不能,因为发送只能异步完成,不能同步完成。
但是我们可以像数据包排队一样对刷新进行排队。即:在发送前一个数据包后发送每个数据包。因此,我们将在每次事件循环处理所有其他工作时发送它。成语是零持续时间计时器 - 请注意,这与计时器完全无关,这是计时器概念的奇怪重载,否则真的没有意义。
int i = 10;
while (i--)
QTimer::singleShot(0, this, [this]{ m_btSocket.write("<some payload>"); });
m_btSocket
必须是类的成员,并且必须是值成员 - 否则代码将不安全。
如果您希望确保在断开连接时转储过时的数据包,并且不会影响任何后续连接,请跟踪它们的生成并仅在它是最新的时才发送:
class Foo : public QObject {
unsigned int m_generation = {}; // unsigned: modulo math w/o overflows
QBluetoothSocket m_btSocket{QBluetoothServiceInfo::L2CAP};
...
bool isBtConnected() const { return m_btSocket::state() == QBluetoothSocket::ConnectedState; }
void sendSinglePacket(const QByteArray & data) {
if (!isBtConnected()) return;
auto gen = m_generation;
QTimer::singleShot(0, this, [this, gen, data] {
if (m_generation == gen)
m_btSocket.write(data);
});
}
Foo(QObject * parent = {}) : QObject(parent) {
connect(&m_btSocket, &QBluetoothSocket::Disconnected, this, [this]{
m_generation++; // drops all in-flight packets
});
...
}
};
我没有使用QBluetoothSocket
的方法找到合适的解决方案,但我通过一些技巧使它工作。
刚刚使用了 C 标头sys/socket.h
(我需要仅支持 POSIX 兼容操作系统)并更改
btSock.write("<some payload>");
自
send(btSock.socketDescriptor(), "<some payload>", <payload length>);
- 如何在 XML 中正确存储原始字节数据并恢复它?
- 如何查看async_accept故障的原始 tcp 数据?
- 读取C++的原始字节数据
- 如何从C++中的原始指针数据构造张量流::张量
- 从数据库中以 blob 数据类型形式存储的原始图像数据中检索 CImage 对象
- 如何使用 C/C++获取原始相机数据
- 在 C++ 中使用 libsndfile 从 WAV 文件中提取原始音频数据
- 使用 ADO 将原始文件数据插入访问表的 BLOB("OLE 对象")字段
- Qt/C++-转换原始二进制数据并将其显示为图像(即QImage)
- 为什么我必须将原始图像数据的宽度除以3
- 在Windows中更改原始波形数据的音高
- 使用FAAC编码到m4a的原始PCM数据是不可识别的
- 如何使用boost::asio发送原始二进制数据
- 用OpenGL在Qt中显示DirectShow的原始图像数据
- 通过原始缓冲区数据缩放和旋转纹理到另一个纹理上
- 从原始缓冲区数据创建Mat图像
- 将原始mono8数据转换为PNG时,加快PNG++的速度
- 转储原始图像数据
- 如何正确接收和发送原始红外数据从Arduino
- 如何将原始图像数据保存为png图像