python - 使用Qt通过蓝牙发送多个原始数据包

标签 python c++ qt sockets bluetooth

我编写了这段 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

更新:

看文档说是这样的

The bytes are written when control goes back to the event loop

如何在返回事件循环之前强制刷新缓冲区?

最佳答案

How could I force buffer to flush before going back to the event loop?

你不能,因为发送只能异步完成,不能同步。

但是我们可以像数据包排队一样对刷新进行排队。即:在发送前一个数据包后发送每个数据包。因此,我们将在每次事件循环处理完所有其他工作时发送它。其成语是零持续时间计时器 - 请注意,这与计时器没有任何关系,它是计时器概念的一种奇怪的重载,否则真的没有任何意义。

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
    });
    ...
  }
};

关于python - 使用Qt通过蓝牙发送多个原始数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48367819/

相关文章:

c++ - 我可以用什么来替换我的 Qt 应用程序中的 sleep 和 usleep?

python - python中奇怪的选择错误

python - 在 Python 中向实例方法添加属性

python - 如何使用基类类型提示在函数中传递子类

c++ - CMake:如何将 .obj 3d 模型添加到 C++ Visual Studio UWP 项目

c++ - 如何在 OpenCV 中将 4 维矩阵转换为 NHWC 格式

python - 如何用 Pandas 替换数据框的所有行?

c++ - 我在哪里可以获得 pkfuncs.h(以及对 KernelIoControl 的访问权限)?

c++ - 自定义 QDateEdit 样式

c++ - header 包含 C++ 库中的路径 - 最佳实践