MTU (Maximum Transmission Unit) là kích thước tối đa của dữ liệu hữu ích trong một gói BLE có thể được truyền giữa các thiết bị trong một giao dịch GATT duy nhất. Trong BLE Classic (4.x), MTU được cố định ở mức 23 byte, đủ cho các lần đọc cảm biến nhỏ nhưng không đủ để truyền tệp hoặc cập nhật OTA. Bluetooth Core Specification 4.2 (2014) đã giới thiệu quy trình MTU Size Request, cho phép thương lượng MTU lớn hơn — lên đến 247 byte (BLE 5.0 — lên đến 251 byte). Cấu hình MTU đúng là một trong những yếu tố hiệu suất chính của các ứng dụng BLE truyền lượng lớn dữ liệu.
Các điểm chính
Maximum Transmission Unit (MTU) trong bối cảnh BLE là kích thước tối đa của Đơn vị Dữ liệu Giao thức Ứng dụng (APDU) mà một thiết bị có thể chấp nhận trong một yêu cầu GATT duy nhất. MTU được định nghĩa ở cấp ATT (Attribute Protocol) và bao gồm tiêu đề ATT (1 byte) + dữ liệu hữu ích. Theo mặc định, tất cả các thiết bị BLE đều hỗ trợ MTU 23 byte (23 = 1 byte tiêu đề ATT + 22 byte dữ liệu).
MTU không phải là giới hạn vật lý của kênh vô tuyến, mà là một thỏa thuận giữa các thiết bị ở cấp GATT. Kích thước vật lý của gói BLE ở Lớp Liên kết (Link Layer) có thể lớn hơn (tối đa 27 byte trong BLE 4.0, tối đa 257 byte trong BLE 5.0 với Data Length Extension), nhưng lớp GATT giới hạn lượng dữ liệu được truyền mỗi giao dịch. Data Length Extension (DLE) là một cơ chế Lớp Liên kết riêng biệt giúp tăng gói vật lý lên 251 byte và phải được thương lượng riêng.
Sự khác biệt giữa MTU và DLE: ATT MTU — lượng dữ liệu được truyền mỗi yêu cầu GATT, DLE — lượng dữ liệu có thể vừa trong một gói Lớp Liên kết. Để đạt tốc độ tối đa, cần thương lượng cả hai tham số. Nếu không có DLE, ngay cả với MTU 247 byte, dữ liệu sẽ bị phân mảnh thành nhiều gói Lớp Liên kết 27 byte, làm giảm thông lượng.
MTU Size Request — một quy trình do Central khởi tạo sau khi thiết lập kết nối GATT. Central gửi một yêu cầu MTU Request chỉ định dung lượng MTU của nó (kích thước tối đa mà nó có thể chấp nhận). Peripheral trả lời bằng MTU Response với giá trị riêng của nó. MTU kết quả là giá trị nhỏ hơn trong hai giá trị. Nếu Central đề xuất MTU 512 và Peripheral chỉ hỗ trợ 128, kết nối sẽ sử dụng MTU 128.
import CoreBluetooth
// Yêu cầu MTU tối đa trên iOS
func requestMTU(central: CBCentralManager,
peripheral: CBPeripheral) {
peripheral.maximumWriteValueLength(
for: .withoutResponse
)
// iOS tự động thương lượng MTU khi kết nối
// MTU = 512 cho thiết bị BLE 5.0
let mtu = peripheral.maximumWriteValueLength(
for: .withResponse
)
print("MTU đã thương lượng: " +
String(mtu))
}
Thời điểm thương lượng: yêu cầu MTU Request nên được gửi sau khi khám phá dịch vụ (discoverServices), nhưng trước khi bắt đầu truyền dữ liệu chủ động. Trong iOS Core Bluetooth, MTU được thương lượng tự động khi kết nối — nhà phát triển không cần gửi MTU Request thủ công. Trên Android, cần gọi requestMTU một cách tường minh. Sau khi được thương lượng, MTU vẫn cố định cho kết nối đó — không thể thương lượng lại nếu không ngắt kết nối và kết nối lại.
ATT (Attribute Protocol) — giao thức mà GATT được xây dựng trên đó. Một gói ATT có kích thước tối đa là 257 byte (ATT_MTU-1). Trong đó, 1 byte là Opcode (loại thao tác), 1 byte là Handle và tối đa 255 byte là Value. Do đó, MTU tối đa được phép theo đặc tả ATT là 257 byte (nhưng trong thực tế, tối đa 251 byte được sử dụng vì một số trường chi phí vẫn cần thiết).
Để gửi dữ liệu lớn hơn MTU, phân mảnh (fragmentation) được sử dụng ở cấp ứng dụng. Nhà phát triển tự chia dữ liệu thành các đoạn có kích thước ≤ MTU và gửi chúng tuần tự. Mỗi đoạn được gửi dưới dạng một yêu cầu GATT Write Request riêng biệt. Bên nhận tập hợp các đoạn thành một bộ đệm duy nhất. GATT không có hỗ trợ phân mảnh tích hợp — đây là trách nhiệm của nhà phát triển.
| Phiên bản BLE | MTU Tối đa | DLE Tối đa | Giới hạn ATT MTU |
|---|---|---|---|
| BLE 4.0 / 4.1 | 23 byte | 27 byte | ATT cố định |
| BLE 4.2 | 247 byte | 251 byte | 257 byte |
| BLE 5.0 | 251 byte | 251 byte | 257 byte |
| Android + iOS | 512 / 517 | 251 byte | Vượt quá ATT |
Thực tế thú vị: iOS và Android yêu cầu MTU 512 và 517 byte tương ứng, nhưng giá trị này vượt quá giới hạn ATT. Trong thực tế, ngăn xếp BLE tự động phân mảnh dữ liệu này, gửi chúng dưới dạng nhiều yêu cầu GATT tuần tự tối đa 251 byte mỗi yêu cầu. Đối với nhà phát triển, sự khác biệt là trong suốt — writeValue hoạt động với mọi kích thước lên đến 512 byte trên iOS.
Kích thước MTU ảnh hưởng trực tiếp đến thông lượng kết nối BLE. Với MTU 23 byte, tốc độ truyền hữu ích tối đa là khoảng 7–10 KB/s trong điều kiện lý tưởng. Tăng MTU lên 247 byte nâng tốc độ lên 60–90 KB/s (với DLE và khoảng thời gian kết nối tối ưu). Điều này đặc biệt quan trọng đối với các ứng dụng truyền hình ảnh, đoạn âm thanh hoặc nhật ký.
Hiệu suất truyền BLE phụ thuộc vào ba yếu tố: MTU (lượng dữ liệu mỗi yêu cầu ATT), khoảng thời gian kết nối (tần suất các sự kiện trao đổi) và DLE (lượng dữ liệu mỗi gói Lớp Liên kết). Cấu hình tối ưu cho tốc độ tối đa: MTU = 247, DLE = 251, khoảng thời gian kết nối = 7,5 ms (giá trị tối thiểu).
Theo Bluetooth SIG White Paper (2023), việc tăng MTU từ 23 lên 247 byte với khoảng thời gian kết nối 30 ms làm tăng thông lượng từ 8 KB/s lên 42 KB/s — tăng gấp 5 lần. Với khoảng thời gian kết nối 7,5 ms, thông lượng đạt 88 KB/s. Đối với các ứng dụng không yêu cầu tốc độ cao (cảm biến nhiệt độ, đèn hiệu BLE), MTU tiêu chuẩn 23 byte vẫn đủ.
iOS Core Bluetooth tự động thương lượng MTU khi kết nối với Peripheral. Nhà phát triển có thể truy vấn MTU hiện tại qua maximumWriteValueLength, nhưng không thể thiết lập thủ công. iOS sử dụng MTU lên đến 512 byte cho thiết bị BLE 5.0 và lên đến 247 cho BLE 4.2. Để ghi lượng lớn dữ liệu, hãy sử dụng writeType: .withResponse để đảm bảo gửi thành công.
// Yêu cầu MTU trên Android (Kotlin)
val bluetoothGatt: BluetoothGatt = ...
// Yêu cầu MTU 517 byte
bluetoothGatt.requestMtu(517)
// Xử lý kết quả trong callback
override fun onMtuChanged(
gatt: BluetoothGatt,
mtu: Int,
status: Int
) {
if (status == BluetoothGatt.GATT_SUCCESS) {
println("MTU negotiated: $mtu")
}
}
Android cung cấp BluetoothGatt.requestMtu(int), cho phép yêu cầu bất kỳ MTU nào lên đến 517 byte. MTU thực tế được xác định bởi thiết bị ngoại vi — nếu nó chỉ hỗ trợ 23 byte, Android sẽ trả về MTU 23. Để xác định MTU hiện tại, hãy sử dụng gatt.requestMtu(0) — thao tác này trả về giá trị hiện tại mà không cố gắng thay đổi nó. Android 12+ hỗ trợ thương lượng MTU tự động khi kết nối qua TRANSPORT_LE.
Các framework đa nền tảng (Flutter, React Native) thường cung cấp API cho requestMTU. Trong thư viện FlutterBlue Plus, MTU được đặt làm tham số kết nối. Trong RxAndroidBle — thông qua phương thức requestMtu. Luôn khuyến nghị thương lượng MTU tối đa ngay sau khi khám phá dịch vụ, trước khi bắt đầu truyền dữ liệu, để tránh phân mảnh ở cấp ứng dụng.
Cập nhật firmware OTA (Over-The-Air) — kịch bản đòi hỏi MTU nhất trong BLE. Kích thước firmware điển hình của thiết bị IoT là 100–500 KB. Với MTU 23 byte và khoảng thời gian kết nối 30 ms, truyền 100 KB mất khoảng 2–3 phút. Với MTU 247 byte và DLE 251 byte — 20–40 giây. Và với MTU 512 byte (iOS) — 10–15 giây.
Quy trình cập nhật OTA thường bao gồm: phân mảnh firmware thành các gói có kích thước ≤ MTU, gửi tuần tự qua Notify/Write, xác minh tổng kiểm tra trên mỗi gói và xác nhận đã nhận. Nếu một gói bị mất, thiết bị yêu cầu gửi lại. Độ tin cậy của OTA phụ thuộc rất nhiều vào việc chọn đúng MTU và khoảng thời gian kết nối.
Khuyến nghị cho OTA: thương lượng MTU tối đa (247–512 byte), đặt khoảng thời gian kết nối là 7,5–15 ms (nếu thiết bị hỗ trợ), sử dụng DLE (Data Length Extension) để tăng gói vật lý lên 251 byte. Đối với thiết bị có bộ nhớ đệm hạn chế (ví dụ: mô-đun BLE dựa trên nRF52), hãy kiểm tra MTU tối đa trong thông số kỹ thuật của chip.
Câu hỏi thường gặp
Kết nối sẽ sử dụng MTU mặc định — 23 byte. Đối với hầu hết các kịch bản IoT (truyền dữ liệu cảm biến), điều này là đủ. Để truyền lượng lớn dữ liệu, tốc độ sẽ thấp hơn 5–10 lần so với MTU đã thương lượng 247 byte.
Không, MTU được thương lượng một lần sau khi kết nối và không thể thay đổi nếu không ngắt kết nối và kết nối lại. Do đó, nên thương lượng MTU ngay sau khi khám phá dịch vụ, trước khi bắt đầu truyền dữ liệu chủ động.
Đây là các mức tối đa thực nghiệm được thiết lập trong lịch sử cho mỗi ngăn xếp. ATT MTU thực tế vẫn bị giới hạn ở 257 byte theo đặc tả. Các ngăn xếp tự động phân mảnh dữ liệu lớn hơn 251 byte thành nhiều gói, vì vậy sự khác biệt giữa 512 và 517 là không đáng kể.
MTU — kích thước của yêu cầu GATT ở cấp ATT. DLE — kích thước của gói vật lý ở Lớp Liên kết. Nếu không có DLE, mỗi yêu cầu GATT (lên đến 247 byte) bị phân mảnh thành các gói 27 byte. Với DLE, nó được truyền dưới dạng một gói duy nhất. Để đạt tốc độ tối đa, cần thương lượng cả hai tham số.
Đối với thiết bị theo dõi sức khỏe truyền dữ liệu nhịp tim và số bước, MTU tiêu chuẩn 23 byte là đủ. Nếu bạn cần truyền lịch sử tập luyện (10–50 KB), hãy thương lượng MTU 247 byte để tăng tốc đồng bộ dữ liệu khi kết nối với điện thoại thông minh.
Tóm tắt
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm