在 C 與 Bluez
int get_l2cap_connection () {
首先,我們需要的所有變數,將在適當的位置進行解釋。
int ssock = 0;
int csock = 0;
int reuse_addr = 1;
struct sockaddr_l2 src_addr;
struct bt_security bt_sec;
int result = 0;
首先,我們需要建立一個套接字,我們可以接受來自的連線。socket 系列是 PF_BLUETOOTH
,socket 型別是 SOCK_SEQPACKET
(我們想要一個類似 TCP 的套接字,而不是 raw),協議是藍芽協議 L2CAP(BTPROTO_L2CAP
)。
ssock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
我們想確保它是成功的:
if (ssock < 0) {
perror("Opening L2CAP socket failed");
return -1;
}
我們現在必須使用萬用字元地址填充源地址結構,因此任何具有任何地址的藍芽裝置都可以連線到我們。萬用字元地址在 bluetooth.h
中定義為 BDADDR_ANY
。要將其複製到地址結構中,我們可以使用 bacpy
函式。我們還必須設定地址系列,地址型別和通道 ID。
memset(&src_addr, 0, sizeof(src_addr));
bacpy(&src_addr.l2_bdaddr, BDADDR_ANY);
src_addr.l2_family = AF_BLUETOOTH;
src_addr.l2_bdaddr_type = BDADDR_LE_PUBLIC;
src_addr.l2_cid = htobs(CID_ATT);
設定 SO_REUSEADDR 選項將允許我們在必要時再次快速呼叫 bind(這可以省略):
setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));
接下來,我們必須使用剛剛定義的源地址結構繫結套接字。我們再次檢查返回值以確保它有效。
result = bind(ssock, (struct sockaddr*) &src_addr, sizeof(src_addr));
if (result < 0) {
perror("Binding L2CAP socket failed");
return -1;
}
接下來是設定安全級別。請注意,此步驟是可選的,但將安全級別設定為 MEDIUM 將允許自動與裝置配對(核心處理實際配對)。
memset(&bt_sec, 0, sizeof(bt_sec));
bt_sec.level = BT_SECURITY_MEDIUM;
result = setsockopt(ssock, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, sizeof(bt_sec));
if (result != 0) {
perrorno("Setting L2CAP security level failed");
return -1;
}
現在我們可以告訴核心我們的 ssock 是一個被動套接字,它將接受一個連線。第二個引數是積壓。如果你想了解更多資訊,listen 的聯機幫助頁面包含你需要的所有資訊。
result = listen(ssock, 10);
if (result < 0) {
perror("Listening on L2CAP socket failed");
return -1;
}
現在我們可以等待傳入的連線。一旦 accept 返回,peer_addr 結構將包含所連線裝置的地址。csock 將是我們可以讀取/寫入的套接字的檔案描述符,以便與連線的裝置進行通訊。
memset(peer_addr, 0, sizeof(*peer_addr));
socklen_t addrlen = sizeof(*peer_addr);
csock = accept(ssock, (struct sockaddr*)peer_addr, &addrlen);
if (csock < 0) {
perror("Accepting connection on L2CAP socket failed");
return -1;
}
我們可以列印連線裝置的地址(當然是可選的)。我們可以使用 batostr 函式將藍芽地址轉換為字串。
printf("Accepted connection from %s", batostr(&peer_addr->l2_bdaddr));
如果我們不想要任何其他裝置連線,我們應該關閉伺服器套接字。在與裝置通訊完成後,使用 csock 執行相同的操作。
close(ssock);
return csock;
}