【问题标题】:Sending multiple raw packet over Bluetooth with Qt使用 Qt 通过蓝牙发送多个原始数据包
【发布时间】:2018-06-30 06:31:25
【问题描述】:

我编写了这个 Python 代码的 sn-p 代码(使用 pybluez)通过 L2CAP 发送原始 BNEP 蓝牙数据包。目的是做一些类似 fuzzing 的测试。

 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?

更新:

查看它说的文档

当控制返回事件循环时写入字节

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

【问题讨论】:

    标签: python c++ qt sockets bluetooth


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

      使用QBluetoothSocket 的方法我没有找到合适的解决方案,但我通过一些小技巧使它工作。

      刚刚使用了 C 头 sys/socket.h(我只需要支持 POSIX 兼容的操作系统)并进行了更改

      btSock.write("<some payload>");
      

      到

      send(btSock.socketDescriptor(), "<some payload>", <payload length>);
      

      【讨论】:

        猜你喜欢
        • 2014-11-16
        • 2016-05-25
        • 2012-02-14
        • 2013-09-27
        • 2015-04-21
        • 1970-01-01
        • 2021-08-16
        • 1970-01-01
        相关资源
        最近更新 更多