连接Android蓝牙客户端套接字到Ubuntu服务器套接字的问题
问题描述:
我正在编写一个Android应用程序,它应该使用C(或C++)中的bluez库,通过蓝牙与运行Ubuntu的PC上的服务器端交换数据, 。连接Android蓝牙客户端套接字到Ubuntu服务器套接字的问题
当我尝试连接到PC上的服务器套接字时,我的Android应用程序失败(IOException)。
这里基本上是我在Java代码(在Android中,这里充满Eclipse项目:http://dl.dropbox.com/u/2968234/ThinBTClient.zip)
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static String address = "00:02:72:B2:85:C7"; // Hard coded for simplicity
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothSocket btSocket = null;
.....
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
btSocket.connect(); // This throws IOException after a timeout of 10seconds or so.
在服务器端(在Ubuntu 8.10),我基本上建立了一个蓝牙服务器插槽,沿着示例bluez/sdp-register.c中描述的路线运行。
下面是我的C++程序。编译它做
g++ -I/usr/include/glib-2.0/ -I/usr/lib/glib-2.0/include -o bt_server bt_server.cpp -lbluetooth
我可以做反向成功地,即在Android中创建一个服务器套接字,并从Linux的连接,但是这不是我想做的事! 我认为或者问题与我的Ubuntu配置有关,但我似乎无法弄清楚这一点,任何帮助将不胜感激!
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sco.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/l2cap.h>
#include <glib.h>
sdp_session_t* register_service(uint8_t rfcomm_channel)
{
// Adapted from http://www.btessentials.com/examples/bluez/sdp-register.c
uint32_t svc_uuid_int[] = { 0x01110000, 0x00100000, 0x80000080, 0xFB349B5F };
const char *service_name = "Roto-Rooter Data Router";
const char *svc_dsc = "An experimental plumbing router";
const char *service_prov = "Roto-Rooter";
uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid,
svc_class_uuid;
sdp_list_t *l2cap_list = 0,
*rfcomm_list = 0,
*root_list = 0,
*proto_list = 0,
*access_proto_list = 0,
*svc_class_list = 0,
*profile_list = 0;
sdp_data_t *channel = 0;
sdp_profile_desc_t profile;
sdp_record_t record = { 0 };
sdp_session_t *session = 0;
// set the general service ID
sdp_uuid128_create(&svc_uuid, &svc_uuid_int);
sdp_set_service_id(&record, svc_uuid);
char str[256] = "";
sdp_uuid2strn(&svc_uuid, str, 256);
printf("Registering UUID %s\n", str);
// set the service class
sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID);
svc_class_list = sdp_list_append(0, &svc_class_uuid);
sdp_set_service_classes(&record, svc_class_list);
// set the Bluetooth profile information
sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
profile.version = 0x0100;
profile_list = sdp_list_append(0, &profile);
sdp_set_profile_descs(&record, profile_list);
// make the service record publicly browsable
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
root_list = sdp_list_append(0, &root_uuid);
sdp_set_browse_groups(&record, root_list);
// set l2cap information
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
l2cap_list = sdp_list_append(0, &l2cap_uuid);
proto_list = sdp_list_append(0, l2cap_list);
// register the RFCOMM channel for RFCOMM sockets
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
sdp_list_append(rfcomm_list, channel);
sdp_list_append(proto_list, rfcomm_list);
access_proto_list = sdp_list_append(0, proto_list);
sdp_set_access_protos(&record, access_proto_list);
// set the name, provider, and description
sdp_set_info_attr(&record, service_name, service_prov, svc_dsc);
// connect to the local SDP server, register the service record,
// and disconnect
session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
sdp_record_register(session, &record, 0);
// cleanup
sdp_data_free(channel);
sdp_list_free(l2cap_list, 0);
sdp_list_free(rfcomm_list, 0);
sdp_list_free(root_list, 0);
sdp_list_free(access_proto_list, 0);
sdp_list_free(svc_class_list, 0);
sdp_list_free(profile_list, 0);
return session;
}
int main(int argc, char **argv)
{
int port = 3;
sdp_session_t* session = register_service(port);
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
printf("socket() returned %d\n", s);
// 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) port;
int r;
r = bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
printf("bind() on channel %d returned %d\n", port, r);
// put socket into listening mode
r = listen(s, 1);
printf("listen() returned %d\n", r);
//sdpRegisterL2cap(port);
// accept one connection
printf("calling accept()\n");
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
printf("accept() returned %d\n", client);
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);
sdp_close(session);
return 0;
}
答
请确保您所创建的服务器套接字注册在SDP与您的客户端尝试连接相同的UUID你的Ubuntu服务器上。
您可以使用$ sdptool browse 00:02:72:B2:85:C7
执行sdp查找/转储,但必须从另一台计算机上运行它。
答
如果在发生错误之前有10秒的延迟,那么看起来像是超时而不是应用程序/ etc层配置错误。您的PC中的蓝牙适配器是否处于“可连接”模式? (例如,“sudo/usr/sbin/hciconfig ”是否包含PSCAN?)
(顺便说一下,sdp_set_service_classes显然会覆盖之前对sdp_set_service_id的调用)。
我试过了,服务器似乎被正确注册在SDP: $ sdptool可以浏览00:02:72:B2:85:C7 服务名称:鼓式Rooter公司数据路由器 服务说明:实验水暖路由器 服务提供者:鼓式拔根 服务RecHandle:0x10004 服务类ID列表: “串行端口”(0x1101) 协议描述符列表: 资料描述符列表: “串行端口”(0x1101) 版本: 0x0100 我仍然得到除离子在我的Android应用程序.. – UlrikK 2010-08-20 12:17:30