运行 一台机器上的两个蓝牙程序使用两个适配器
Running two Bluetooth programs on one machine using two adapters
新建Post
我现在对我的问题有了更好的理解,我不会创建一个新线程,而是只更新这个线程。
所以使用 hci_open_dev
是错误的,因为它只打开本地 BT 适配器的套接字。它无法帮助我建立与远程设备的连接。
总而言之 - 我的笔记本电脑中有一个内置的 BT 适配器,我已经购买了一个小型 USB BT 适配器,并将其插入同一台笔记本电脑。现在我想运行这台机器上的两个程序可以通信。为此,他们需要使用不同的适配器。
bind
的第二个参数是一个 struct sockaddr*
,我只是简单地将我之前的 struct sockaddr_rc*
转换为。 listening 套接字 struct sockaddr
的 bdaddr_t
字段指定要使用的 BT 适配器,允许我这样做:
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
// address of the built in BT adapter on my machine
const char* adapter = "60:F2:62:1B:9C:74";
// converting it to a bdaddr_t*
bdaddr_t* adapterbdadd = strtoba(adapter);
// allocate socket
int s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// bind socket to port 1
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *adapterbdadd;
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// set the socket to listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
// convert the bdaddr to a char* (just assume buf is defined elsewhere)
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
// free socket resources
close(client);
close(s);
但是,对于传出连接,我不确定如何指定要使用的适配器。代码大致如下所示:
struct sockaddr_rc addr = { 0 };
// This is the same address that should be used by the listening program above
char dest[18] = "60:F2:62:1B:9C:74";
// allocate a socket
int s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// set the connection parameters. Want to connect to the listening program
// and connect through port 1. If I change both programs to use port 0 I
// get an Invalid Argument error from this program.
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( dest, &addr.rc_bdaddr );
// connect to listening program
int status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
// This program never reaches beyond this point
if( status == 0 ) {
printf("successfully connected\n");
} else {
perror("error connecting");
}
close(s);
如上所示,我只能指定连接到哪个设备,使用哪个设备。当我第一次启动客户端后面的监听程序时,连接永远不会建立。 运行ning hciconfig
的输出如下所示:
hci1: Type: Primary Bus: USB
BD Address: 60:F2:62:1B:9C:74 ACL MTU: 1021:4 SCO MTU: 96:6
UP RUNNING
RX bytes:16967 acl:0 sco:0 events:2751 errors:0
TX bytes:678007 acl:0 sco:0 commands:2749 errors:0
hci0: Type: Primary Bus: USB
BD Address: 5C:F3:70:9D:BC:07 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING
RX bytes:1016 acl:0 sco:0 events:57 errors:0
TX bytes:3679 acl:0 sco:0 commands:57 errors:0
我不是 BT 专家,但我在这里没有看到任何值得警惕的东西。还有人吗? 如果有人能指出为什么这两个程序不能相互通信,我将非常感激。
旧Post
我正在我的笔记本电脑上开发一些蓝牙 (BT)(普通蓝牙,不是低功耗蓝牙)软件,为了在一台机器上测试它们,我买了第二个 BT 适配器 (Asus USB-BT400)。插入后,我可以立即使用 hciconfig
.
看到它
我试图调整我的程序以使用正确的适配器,但它不起作用,我不确定为什么。我对 BT 编程很陌生,所以我可能误解了一些东西。让程序 A 使用地址为 addr1
的适配器 I 运行
int dev_id = hci_devid("60:F2:62:1B:9C:74");
int err = hci_open_dev(dev_id);
if(err < 0) {
printf("error opening adapter device\n");
}
其中 "60:F2:62:1B:9C:74"
是 addr1
。配套程序做了同样的事情,但使用了其他适配器地址。
当我 运行 这两个程序时,没有打印错误(意味着适配器选择成功?)但是程序什么都不做。一段时间后,客户端程序打印 Uh Oh! The Host is Down
。 如果有人能解释我在选择适配器时做错了什么,我将不胜感激。我还尝试 运行 在一台笔记本电脑上连接服务器,在另一台笔记本电脑上连接客户端,但也没有任何反应。在那种情况下,我没有明确选择 BT 适配器,因为我希望它默认为唯一可用的适配器。我没有考虑到示例代码可能有误,但如果有人看到任何错误,请指出。
完整代码见下。我正在尝试 运行 一个在服务器和客户端之间使用 RFCOMM 连接的简单示例。这个例子是从Albert S. Huang和Larry Rudolph的《Bluetooth essentials for programmers》一书中借用的,之后我尝试修改它。
服务器程序
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
int dev_id = hci_devid("60:F2:62:1B:9C:74");
int err = hci_open_dev(dev_id);
if(err < 0) {
printf("error opening laptop device\n");
}
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// bind socket to port 1 of the first available
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
// read data from the client
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
}
// close connection
close(client);
close(s);
return 0;
}
客户端程序
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
int main(int argc, char **argv)
{
struct sockaddr_rc addr = { 0 };
int s, status;
char dest[18] = "60:F2:62:1B:9C:74";
int dev_id = hci_devid("5C:F3:70:9D:BC:07");
int err = hci_open_dev(dev_id);
if(err < 0) {
printf("error opening adapter device\n");
}
// allocate a socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// set the connection parameters (who to connect to)
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( dest, &addr.rc_bdaddr );
// connect to server
status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
// send a message
if( status == 0 ) {
status = write(s, "hello!", 6);
}
if( status < 0 ) perror("uh oh");
close(s);
return 0;
}
好的,我在 Zephyr 的 slack 频道中得到了用户@hje 和@sjanc 的一些帮助。有几件事我必须改变。首先,我把strtoba
的用法改成了str2ba
。 strtoba
做了一些奇怪的交换。
其次,即使是客户端程序也可以通过bind
指定使用哪个BT适配器,类似于服务器程序的方式。在我的例子中,我首先启动服务器,然后客户端将分配空闲的适配器。我不需要明确说明是哪个。
最后,但绝对最重要的是,事实证明您必须指示 Linux 才能使 BT 适配器可被发现。我通过 运行 hciconfig hci0 piscan
和 hciconfig hci1 piscan
.
做到了这一点
最后完成的节目:
客户
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
int main(int argc, char **argv)
{
struct sockaddr_rc addr = { 0 }, laddr = {0};
int s, status;
char dest[18] = "60:F2:62:1B:9C:74";
// allocate a socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// set the connection parameters (who to connect to)
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( dest, &addr.rc_bdaddr );
// connect to server
status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
// send a message
if( status == 0 ) {
printf("successfully connected\n");
}
close(s);
return 0;
}
服务器
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
// I want to use the built in BT adapter
const char* adapter = "60:F2:62:1B:9C:74";
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// bind socket to port 1 of the first available
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
str2ba(adapter, &loc_addr.rc_bdaddr);
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
// close connection
close(client);
close(s);
return 0;
}
新建Post
我现在对我的问题有了更好的理解,我不会创建一个新线程,而是只更新这个线程。
所以使用 hci_open_dev
是错误的,因为它只打开本地 BT 适配器的套接字。它无法帮助我建立与远程设备的连接。
总而言之 - 我的笔记本电脑中有一个内置的 BT 适配器,我已经购买了一个小型 USB BT 适配器,并将其插入同一台笔记本电脑。现在我想运行这台机器上的两个程序可以通信。为此,他们需要使用不同的适配器。
bind
的第二个参数是一个 struct sockaddr*
,我只是简单地将我之前的 struct sockaddr_rc*
转换为。 listening 套接字 struct sockaddr
的 bdaddr_t
字段指定要使用的 BT 适配器,允许我这样做:
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
// address of the built in BT adapter on my machine
const char* adapter = "60:F2:62:1B:9C:74";
// converting it to a bdaddr_t*
bdaddr_t* adapterbdadd = strtoba(adapter);
// allocate socket
int s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// bind socket to port 1
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *adapterbdadd;
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// set the socket to listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
// convert the bdaddr to a char* (just assume buf is defined elsewhere)
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
// free socket resources
close(client);
close(s);
但是,对于传出连接,我不确定如何指定要使用的适配器。代码大致如下所示:
struct sockaddr_rc addr = { 0 };
// This is the same address that should be used by the listening program above
char dest[18] = "60:F2:62:1B:9C:74";
// allocate a socket
int s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// set the connection parameters. Want to connect to the listening program
// and connect through port 1. If I change both programs to use port 0 I
// get an Invalid Argument error from this program.
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( dest, &addr.rc_bdaddr );
// connect to listening program
int status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
// This program never reaches beyond this point
if( status == 0 ) {
printf("successfully connected\n");
} else {
perror("error connecting");
}
close(s);
如上所示,我只能指定连接到哪个设备,使用哪个设备。当我第一次启动客户端后面的监听程序时,连接永远不会建立。 运行ning hciconfig
的输出如下所示:
hci1: Type: Primary Bus: USB
BD Address: 60:F2:62:1B:9C:74 ACL MTU: 1021:4 SCO MTU: 96:6
UP RUNNING
RX bytes:16967 acl:0 sco:0 events:2751 errors:0
TX bytes:678007 acl:0 sco:0 commands:2749 errors:0
hci0: Type: Primary Bus: USB
BD Address: 5C:F3:70:9D:BC:07 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING
RX bytes:1016 acl:0 sco:0 events:57 errors:0
TX bytes:3679 acl:0 sco:0 commands:57 errors:0
我不是 BT 专家,但我在这里没有看到任何值得警惕的东西。还有人吗? 如果有人能指出为什么这两个程序不能相互通信,我将非常感激。
旧Post
我正在我的笔记本电脑上开发一些蓝牙 (BT)(普通蓝牙,不是低功耗蓝牙)软件,为了在一台机器上测试它们,我买了第二个 BT 适配器 (Asus USB-BT400)。插入后,我可以立即使用 hciconfig
.
我试图调整我的程序以使用正确的适配器,但它不起作用,我不确定为什么。我对 BT 编程很陌生,所以我可能误解了一些东西。让程序 A 使用地址为 addr1
的适配器 I 运行
int dev_id = hci_devid("60:F2:62:1B:9C:74");
int err = hci_open_dev(dev_id);
if(err < 0) {
printf("error opening adapter device\n");
}
其中 "60:F2:62:1B:9C:74"
是 addr1
。配套程序做了同样的事情,但使用了其他适配器地址。
当我 运行 这两个程序时,没有打印错误(意味着适配器选择成功?)但是程序什么都不做。一段时间后,客户端程序打印 Uh Oh! The Host is Down
。 如果有人能解释我在选择适配器时做错了什么,我将不胜感激。我还尝试 运行 在一台笔记本电脑上连接服务器,在另一台笔记本电脑上连接客户端,但也没有任何反应。在那种情况下,我没有明确选择 BT 适配器,因为我希望它默认为唯一可用的适配器。我没有考虑到示例代码可能有误,但如果有人看到任何错误,请指出。
完整代码见下。我正在尝试 运行 一个在服务器和客户端之间使用 RFCOMM 连接的简单示例。这个例子是从Albert S. Huang和Larry Rudolph的《Bluetooth essentials for programmers》一书中借用的,之后我尝试修改它。
服务器程序
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
int dev_id = hci_devid("60:F2:62:1B:9C:74");
int err = hci_open_dev(dev_id);
if(err < 0) {
printf("error opening laptop device\n");
}
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// bind socket to port 1 of the first available
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
// read data from the client
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
}
// close connection
close(client);
close(s);
return 0;
}
客户端程序
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
int main(int argc, char **argv)
{
struct sockaddr_rc addr = { 0 };
int s, status;
char dest[18] = "60:F2:62:1B:9C:74";
int dev_id = hci_devid("5C:F3:70:9D:BC:07");
int err = hci_open_dev(dev_id);
if(err < 0) {
printf("error opening adapter device\n");
}
// allocate a socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// set the connection parameters (who to connect to)
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( dest, &addr.rc_bdaddr );
// connect to server
status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
// send a message
if( status == 0 ) {
status = write(s, "hello!", 6);
}
if( status < 0 ) perror("uh oh");
close(s);
return 0;
}
好的,我在 Zephyr 的 slack 频道中得到了用户@hje 和@sjanc 的一些帮助。有几件事我必须改变。首先,我把strtoba
的用法改成了str2ba
。 strtoba
做了一些奇怪的交换。
其次,即使是客户端程序也可以通过bind
指定使用哪个BT适配器,类似于服务器程序的方式。在我的例子中,我首先启动服务器,然后客户端将分配空闲的适配器。我不需要明确说明是哪个。
最后,但绝对最重要的是,事实证明您必须指示 Linux 才能使 BT 适配器可被发现。我通过 运行 hciconfig hci0 piscan
和 hciconfig hci1 piscan
.
最后完成的节目:
客户
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
int main(int argc, char **argv)
{
struct sockaddr_rc addr = { 0 }, laddr = {0};
int s, status;
char dest[18] = "60:F2:62:1B:9C:74";
// allocate a socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// set the connection parameters (who to connect to)
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( dest, &addr.rc_bdaddr );
// connect to server
status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
// send a message
if( status == 0 ) {
printf("successfully connected\n");
}
close(s);
return 0;
}
服务器
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
// I want to use the built in BT adapter
const char* adapter = "60:F2:62:1B:9C:74";
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// bind socket to port 1 of the first available
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
str2ba(adapter, &loc_addr.rc_bdaddr);
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
// close connection
close(client);
close(s);
return 0;
}