C# 我们是否必须在应用程序级别处理蓝牙LE通信中的MTU?

C# 我们是否必须在应用程序级别处理蓝牙LE通信中的MTU?,c#,uwp,bluetooth,bluetooth-lowenergy,C#,Uwp,Bluetooth,Bluetooth Lowenergy,我正在用C#构建一个蓝牙低能耗测试应用程序,让两个Windows 10应用程序进行通信(一个使用商业.NET Framework SDK的中央应用程序,一个使用UWP的外围设备应用程序),我正试着去理解MTU(最大传输单元)的影响在应用程序级别。以下是我目前的理解: 在蓝牙协议栈的L2CAP层,存在一些“大”数据包的碎片和重组。因此,如果数据超过MTU,它将分块发送。 在UWP中,我们使用GattLocalCharacteristic.WriteRequested回调来处理接收到的数据。在我正在

我正在用C#构建一个蓝牙低能耗测试应用程序,让两个Windows 10应用程序进行通信(一个使用商业.NET Framework SDK的中央应用程序,一个使用UWP的外围设备应用程序),我正试着去理解MTU(最大传输单元)的影响在应用程序级别。以下是我目前的理解:

在蓝牙协议栈的L2CAP层,存在一些“大”数据包的碎片和重组。因此,如果数据超过MTU,它将分块发送。 在UWP中,我们使用
GattLocalCharacteristic.WriteRequested
回调来处理接收到的数据。在我正在处理的示例中,当发送2-3K数据时,522字节的每一块(可能是协商的MTU?)都会调用它,因此似乎我必须在应用程序级别处理重组,尽管它应该在L2CAP级别完成(如果我理解正确的话)。这意味着我必须检测数据何时完成(使用某种长度字段“EOF”或任何机制),这会给协议增加一些负担,让我感觉非常低级。我原以为
WriteRequested
事件只会在所有数据都在其中的情况下触发一次

除此之外,UWP SDK(
Windows.Devices.Bluetooth
namespace)似乎没有提供一种了解实际MTU的方法(类似于Android上的
requestMtu
),所以这里我不得不再次定制一些管道


所以我想问题是:我是否必须检测协商的MTU(如何在UWP中?)并自己分割和重新组合数据包?

您不必在windows 10上协商MTU

它仅取决于所使用的蓝牙版本。
BLE4.0/4.1的最大MTU为23字节,BLE4.2的最大MTU为251字节。
对于windows 10上的其他版本,我不知道最大值。
MTU由L2CAP定义,可以是23到无穷大之间的任意值。蓝牙协议栈的实现是确定客户端和外围设备MTU的关键因素。

Windows 10设备将始终尝试协商最大MTU。

ATT数据包可以跨越多个LL数据包。ATT分组内的数据单元的大小称为最大传输单元(MTU)。默认大小为23字节(允许数据包装入一个LL数据包),但该大小可以通过Exchange MTU请求和响应进行协商


根据蓝牙核心规范,属性值(ATT有效负载)的最大允许长度为512字节3。虽然这在技术上意味着MTU大小可以略大于512字节(以适应ATT协议开销),但大多数蓝牙堆栈支持最大512字节的MTU值,windows串行设备使用定时器向事件传递数据。因此,对于任何串行通信设备,您必须知道消息结束的时间,才能可靠地工作。串行设备以数据块的形式获取数据,而传输的数据块可能与接收的数据块不完全相同。据我所知,您只能在WinRT中获取最大PDU大小。在经典蓝牙中,您可以更改(读取和写入)MTU大小。好的,看起来中央的SDK正确封装了碎片/重组,这意味着我可以只写入一次超过MTU的数据,并以数据包的形式发送(多少,大小,我不在乎),但在外围端(UWP)该事件将弹出X次,而不是仅弹出一次,因此它没有得到很好的封装,它迫使我自己重新组合数据包。我理解正确吗?不,这不是保证。接收缓冲区可能会溢出,这样会丢失数据。这取决于SDK和蓝牙协议栈。即使双方都使用蓝牙版本5或更高版本,使用248字节的数据包也更安全。如果您等待GattCommunicationStatus.Success发送下一个数据包之前,您可以尝试更大的数据包,直到数据被截断,或者直到数据处理时间过长,并且接收缓冲区没有足够快地清空。可以安全地说,在UWP上,MTU不受正确级别的支持吗?因为在中央的另一个API中,这是完全透明的。一方面它不应该是透明的(因此不需要数据包分段),另一方面它也不受支持,对吗?Windows文档缺少很多关于蓝牙的信息,尤其是BLE。在这里我发现了很多信息:它与nRF52平台相关,但非常有用。