(Post 24/04/2007) Chúng ta đang sống trong
một thế giới mà các thiết bị không dây dần len lỏi vào cuộc sống của mỗi
gia đình. Từ chiếc điện thoại di động (ĐTDĐ) xinh xắn, thiết bị hỗ trợ
cá nhân đa năng (Pocket PC, Palm...), đến các phương tiện giải trí trong
gia đình như hệ thống loa, đầu DVD, tivi, tất cả được kết nối với nhau
mà không cần một sợi dây nào. Nếu bạn đã từng đặt câu hỏi: "Có thể
lập trình để truyền tải dữ liệu hình ảnh, âm thanh vào ĐTDĐ qua cổng hồng
ngoại hay Bluetooth?" thì bài viết này sẽ giúp bạn hình dung cách
thức và hướng giải quyết vấn đề trên.
Hình 1:
Giao thức OBEX trong mô hình OSI |
|
OBEX LÀ GÌ?
OBEX (OBject EXchange) là giao thức trao đổi dữ liệu
giữa các thiết bị dùng cổng hồng ngoại được hiệp hội IrDA (Infrared Data
Association) đưa ra lần đầu tiên năm 1997. Ban đầu, giao thức này chỉ
giới hạn cho các thiết bị sử dụng môi trường ánh sáng hồng ngoại, nhưng
rất nhanh sau đó nó được tổ chức Bluetooth SIG (Bluetooth Special Interest
Group) đưa vào hầu hết các thiết bị Bluetooth của mình.
1. Vị trí OBEX trong mô hình OSI
Cũng giống như các giao thức khác, giao thức OBEX được
xây dựng trên nền mô hình OSI (Open Systems Interconnection) bao gồm hai
thành phần chính:
- OBEX session protocol (giao thức phiên OBEX): mô tả cấu trúc gói
tin trong phiên làm việc giữa hai thiết bị.
- OBEX application framework: tập các dịch vụ OBEX cung cấp cho các
ứng dụng đầu cuối như truyền file, in ảnh...
2. Cấu trúc gói tin trong giao thức phiên OBEX
Giao thức OBEX được sử dụng chủ yếu trong các ứng dụng
kiểu "đẩy" (Push) hoặc "kéo" (Pull), cho phép máy
khách (client) "đẩy" dữ liệu lên máy chủ (server) hoặc "kéo"
dữ liệu từ server xuống. Để thực hiện điều này, các gói tin trao đổi giữa
client và server phải tuân thủ chặt chẽ cấu trúc đề ra. Dưới đây là một
vài cấu trúc được sử dụng trong quá trình truyền file giữa client và server
(chi tiết có thể tham khảo tài liệu IrOBEX1.3).
2.1 Gói tin yêu cầu
Mọi gói tin yêu cầu đều có cấu trúc như sau:
Byte 0 |
Byte 1, 2 |
Byte 3 đến n |
opcode |
packet length |
Headers |
Opcode: Mã lệnh ứng với từng yêu cầu (Bảng 1). Bit cao
nhất gọi là Final bit.
Packet length: Độ dài của gói tin
Header: Thông tin đầu có cấu trúc như sau:
Byte 0 |
Byte 1, 2 |
Byte 3 đến n |
opcode |
length (tuỳ chọn) |
value |
Bảng 1: Mã lệnh yêu cầu
Mã lệnh |
Kiểu |
Mô tả |
0x80 |
CONNECT |
Thiết lập phiên giao dịch |
0x81 |
DISCONNECT |
Ngừng phiên giao dịch |
0x02 (0x82) |
PUT |
Gửi dữ liệu lên server |
0x03 (0x83) |
GET |
Lấy dữ liệu từ server |
0xFF |
ABORT |
Hủy bỏ phiên giao dịch |
Bảng 2: Thông tin đầu
Định danh |
Tên |
Mô tả |
0x01 |
NAME |
Tên file (mã Unicode) |
0xC3 |
LENGTH |
Kích thước file theo byte |
0x48 |
BODY |
Đoạn dữ liệu của file |
0x49 |
END OF BODY |
Đoạn dữ liệu cuối cùng của file |
2.2 Gói tin trả lời
Giống như gói tin yêu cầu, gói tin trả lời có cấu trúc
như sau:
Byte 0 |
Byte 1, 2 |
Byte 3 to n |
response opcode |
response length |
response data |
Một số mã trả lời (response opcode) thường gặp:
Bảng 3: Mã trả lời
Mã trả lời |
Mô tả |
0x10 (0x90) |
Tiếp tục yêu cầu hoặc trả lời |
0x20 (0xA0) |
Xác nhận kết thúc yêu cầu hoặc trả lời |
0x40 (0xC0) |
Lỗi yêu cầu |
0x41 (0xC1) |
Lỗi do không có quyền |
0x43 (0xC3) |
Phiên giao dịch bị huỷ bỏ |
0x44 (0xC4) |
Không tìm thấy file |
3. Cùng giải quyết
Quá trình trao đổi file giữa client và server được chia
làm 3 giai đoạn:
- Thiết lập phiên: CONNECT
- Nhận/gửi file: GET/PUT
- Ngừng phiên: DISCONNECT
3.1 Thiết lập phiên (CONNECT)
Gói tin CONNECT có cấu trúc như sau:
Byte 0 0 |
Byte 1, 2 |
Byte 3 |
Byte 4 |
Byte 5, 6 |
Byte 7 to n |
0x80 |
packet length |
OBEX version number |
flags |
maximum OBEX packet length |
optional headers |
OBEX version number: Phiên bản giao thức OBEX gồm major
number lưu tại 4 bit cao, minor number lưu tại 4 bit thấp. Phiên bản hiện
tại là 1.0, do đó giá trị này là 0x10.
Flags: Giá trị này luôn là 0x00 trong phiên bản hiện
tại.
Maximum OBEX packet length: Giá trị lớn nhất của gói
tin trong giao thức OBEX mà thiết bị có thể nhận hoặc gửi. Giá trị này
ở client và server có thể khác nhau. Do đó khi thiết lập phiên, client
cần gửi giá trị này lên server để kiểm tra xem kích thước gói tin lớn
nhất mà server có thể nhận hoặc gửi là bao nhiêu?
Optional headers: Thông tin đầu được tùy chọn ứng với
mục đích của mỗi phiên giao dịch. Trong ví dụ dưới đây, giá trị này có
thể bỏ qua.
Yêu cầu từ client |
byte |
Ý nghĩa |
Mã yêu cầu |
0x80 |
CONNECT |
0x0007 |
Độ dài gói tin = 7 bytes |
0x10 |
Phiên bản OBEX 1.0 |
0x00 |
Flags đối với phiên bản hiện tại |
0x2000 |
Kích thước lớn nhất của gói tin là 8K |
Trả lời từ server
Mã trả lời |
0xA0 |
SUCCESS |
|
0x0007 |
Độ dài gói tin = 7 bytes |
|
0x10 |
Phiên bản OBEX 1.0 |
|
0x00 |
Flags đối với phiên bản hiện tại |
|
0x0200 |
Kích thước lớn nhất của gói tin mà server có thể nhận hoặc gửi
là 512 bytes |
3.2 Gửi file (PUT)
Không giống như gói tin CONNECT, gói tin PUT có thêm
một số thông tin đầu sau:
NAME: Thông tin về tên file
LENGTH: Thông tin về kích thước file
BODY: Đoạn dữ liệu file
END OF BODY: Đoạn dữ liệu cuối cùng của file
Dưới đây là ví dụ gửi 1 file hello.gif có kích thước
721 bytes từ client (PC) lên server (ĐTDĐ). Do kích thước của file lớn
hơn kích thước gói tin lớn nhất mà server có thể nhận (với Sony Ericsson
T610 là 512 bytes) nên client sẽ chia file thành hai gói tin để gửi. Gói
tin 1 có mã yêu cầu PUT là 0x02 (không thiết lập Final bit). Gói tin 2
có mã yêu cầu PUT là 0x82 (thiết lập Final bit).
Yêu cầu từ client |
byte |
Ý nghĩa |
Mã yêu cầu |
0x02 |
PUT, Final bit không thiết lập để chỉ cho server biết client
còn gửi yêu cầu tiếp theo |
0x01E2 |
Độ dài gói tin = 482 bytes |
0x01 |
Định danh thông tin đầu NAME (tên file) |
0x0017 |
Độ dài của thông tin đầu NAME = 20+3 = 23 bytes |
hello.gif |
Tên file (unicode) có ký tự kết thúc NULL (20 bytes) |
0xC3 |
Định danh thông tin đầu LENGTH (kích thước file) |
0x000002D1 |
Kích thước file = 721 bytes |
0x48 |
Định danh thông tin đầu BODY (dữ liệu file) |
0x01C3 |
Độ dài của thông tin đầu BODY = 448+3 = 451 bytes |
0x... |
Đoạn dữ liệu file có kích thước 448 bytes |
Trả
lời từ server |
Mã trả lời |
0x90 |
CONTINUE, tiếp tục nhận yêu cầu từ client |
0x0003 |
độ dài gói tin = 3 bytes |
Yêu cầu từ client |
Mã yêu cầu |
0x82 |
PUT, Final bit được thiết lập để chỉ cho server biết đây là gói
tin cuối cùng |
0x0117 |
Độ dài gói tin = 279 bytes |
0x49 |
Định danh thông tin đầu END OF BODY |
0x0114 |
Độ dài của thông tin đầu END OF BODY = 276 bytes |
0x... |
Đoạn dữ liệu file có kích thước 721-448 = 273 bytes |
Trả
lời từ server |
Mã trả lời |
0xA0 |
SUCCESS |
0x0003 |
độ dài gói tin = 3 bytes |
3.3 Nhận file (GET)
Khác với gói tin PUT, gói tin GET chỉ có thông tin đầu
NAME. Ví dụ sau sẽ mô tả quá trình nhận file hello.gif có kích thước 721
bytes từ server. Trước tiên client (PC) sẽ gửi yêu cầu GET đến server
(ĐTDĐ) với thông tin đầu NAME là tên file. Do kích thước của file yêu
cầu lớn hơn 512 bytes (với Sony Ericsson T610) nên gói tin trả lời đầu
tiên có mã trả lời là 0x90 (CONTINUE) cùng với một phần dữ liệu của file.
Khi nhận được mã trả lời là CONTINUE, client biết rằng đây chưa phải là
đoạn dữ liệu cuối cùng của file nên tiếp tục gửi yêu cầu (không cần thông
tin đầu NAME) cho đến khi nhận được mã trả lời là 0xA0 (SUCCESS).
Yêu cầu từ client |
byte |
Ý nghĩa |
Mã yêu cầu |
0x83 |
GET, Final bit được thiết lập |
0x001A |
Độ dài gói tin = 26 bytes |
0x01 |
Định danh thông tin đầu NAME (tên file) |
0x0017 |
Độ dài của thông tin đầu NAME = 20+3 = 23 bytes |
hello.gif |
Tên file (unicode) có ký tự kết thúc NULL (20 bytes) |
Trả
lời từ server |
Mã trả lời |
0x90 |
CONTINUE, còn dữ liệu trên server |
0x01C6 |
Độ dài gói tin = 454 bytes |
0x48 |
Định danh thông tin đầu BODY (dữ liệu file) |
0x01C3 |
Độ dài của thông tin đầu BODY = 448+3 = 451 bytes |
0x... |
Đoạn dữ liệu file có kích thước 448 bytes |
Yêu
cầu từ client |
Mã yêu cầu |
0x83 |
PUT, tiếp tục yêu cầu nhận file |
0x0003 |
Độ dài gói tin = 3 bytes |
Trả
lời từ server |
Mã trả lời |
0xA0 |
SUCCESS, đoạn dữ liệu cuối cùng |
0x0117 |
Độ dài gói tin = 279 bytes |
0x49 |
Định danh thông tin đầu END OF BODY |
0x0114 |
Độ dài của thông tin đầu END OF BODY = 276 bytes |
0x... |
Đoạn dữ liệu file có kích thước 273 bytes |
3.4 Ngừng phiên (DISCONNECT)
Để kết thúc phiên giao dịch, client cần gửi gói tin DISCONNECT
tới server.
Yêu cầu từ client |
byte |
Ý nghĩa |
Mã yêu cầu |
0x81 |
DISCONNECT |
0x0003 |
Độ dài gói tin = 3 bytes |
Trả lời từ server |
Mã trả lời |
0xA0 |
SUCCESS |
0x0003 |
Độ dài gói tin = 3 bytes |
Nguyễn Đức Thắng
thangnd@hitekgroup.net
(theo PC World VN) |