【热门技术】Winsock 搜索蓝牙设备

来源:互联网 发布:记事本编程html 编辑:程序博客网 时间:2024/04/24 10:56

http://blog.csdn.net/JamesXing/article/details/1700338 这里有各种蓝牙相关的文章


我们如何检索计算机上面的蓝牙设备呢,我们使用winsock搜索蓝牙设备,请见代码分析

#include "stdafx.h"

#include <winsock2.h>
#include <ws2bth.h>

#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
// 初始化winsock
WSADATA wsaData;
if( WSAStartup( MAKEWORD(2,2), &wsaData ) != 0 )
{
_tprintf(_T("WSAStartup failed with error code: %d\n"), WSAGetLastError());
return 1;
}

// 初始化蓝牙枚举结构
DWORD dwWsaqsLen = sizeof(WSAQUERYSET);
LPWSAQUERYSET lpWsaqs = (LPWSAQUERYSET)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwWsaqsLen);
lpWsaqs->dwSize = sizeof(WSAQUERYSET);
lpWsaqs->dwNameSpace = NS_BTH;

// 开始枚举蓝牙设备
DWORD dwWsaqsFlags = LUP_CONTAINERS | LUP_FLUSHCACHE | LUP_RETURN_NAME | LUP_RETURN_ADDR;
HANDLE hService;

if(WSALookupServiceBegin(lpWsaqs, dwWsaqsFlags, &hService) != SOCKET_ERROR)
{
bool bFinished = false;
while(!bFinished)
{
if(WSALookupServiceNext(hService, dwWsaqsFlags, &dwWsaqsLen, lpWsaqs) == NO_ERROR)
{
SOCKADDR_BTH *saBth = (SOCKADDR_BTH*)lpWsaqs->lpcsaBuffer->RemoteAddr.lpSockaddr;
BTH_ADDR bthAddr = saBth->btAddr;

_tprintf(_T("\n发现蓝牙设备: \n"));
_tprintf(_T("------------------------\n"));
_tprintf(_T("NAP: 0x%04X SAP: 0x%08X 设备名称: %s\n"), GET_NAP(bthAddr), GET_SAP(bthAddr), lpWsaqs->lpszServiceInstanceName);
}
else
{
// 错误处理
switch(WSAGetLastError())
{
// 所给缓冲区过小,重新申请
case WSAEFAULT:
HeapFree(GetProcessHeap(), 0, lpWsaqs);
lpWsaqs = (LPWSAQUERYSET)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwWsaqsLen);
break;

// 没有更多蓝牙设备了
case WSA_E_NO_MORE:
bFinished = true;
break;

default:
//bFinished = true;
break;
}
}
}
WSALookupServiceEnd( hService );
}

// 释放资源
HeapFree(GetProcessHeap(), 0, lpWsaqs);
WSACleanup();

return 0;
}



使用WinSock连接到远程蓝牙设备

你可以通过创建服务端和客户端套接字来连接两个蓝牙设备。服务端套接字必须设定为监听传入连接并接受客户端套接字;客户端套接字在发送连接请求之前必须要知道要连接到的设备的地址。
你也可以在Microsoft Windows CE上使用串口仿真方便地创建连接,详情参见“利用虚拟串口连接到远程设备”
注意   为了使清晰起见,文中忽略了错误处理
在创建连接前,你必须先获得以下信息:
Ø            要查询的远程设备的地址,BT_ADDR类型,定义在Ws2bth.h中:
typedef ULONGLONG bt_addr, *pbt_addr, BT_ADDR, *PBT_ADDR;
注意   仅仅客户端须要如此。
Ø            一个GUID类型变量的服务标识符,或者RFCOMM通道(1到31)。
创建客户端套接字
1.    提供Winsock的版本和实现细节的数据来初始化caller application。可以通过调用WSAStartup函数来获得这个数据。
WSADATA wsd;
WSAStartup (MAKEWORD(1,0), &wsd);
2.    调用socket函数来创建一个蓝牙套接字。
SOCKET client_socket = socket (AF_BT, SOCK_STREAM, BTHPROTO_RFCOMM);
socket函数的参数值将套接字设置为蓝牙服务。
3.    通过设置SOCKADDR_BTH结构体来储存客户端要连接到的远程设备的信息。
a.    创建并初始化SOCKADDR_BTH变量。
SOCKADDR_BTH sa;
memset (&sa, 0, sizeof(sa));
b.    btAddr成员赋值为包含目标设备地址的BT_ADDR变量。
sa.btAddr = b; //b is a BT_ADDR variable
你的程序可以接受字符串类型的设备地址,但必须将其转换并储存为一个BT_ADDR类型变量。
c.    如果服务标识符有效,则将serviceClassId成员设置为基于RFCOMM的服务的GUID。这种情况下,客户端执行SDP查询然后使用得到的服务器通道。
或者
如果你要使用硬编码的通道编号,将port成员变量设置为服务器通道编号。
sa.port = channel & 0xff;
4.    调用connect函数来连接到蓝牙套接字。
if (connect (client_socket, (SOCKADDR *)&sa, sizeof(sa)))
{
 //Perform error handling.
 closesocket (client_socket);
 return 0;
}
传递第3步中设置好的SOCKADDR_BTH来指定目标设备的属性。
连接建立后,你可以通过发送和接收数据来和目标设备通信。
5.    要关闭与目标设备的连接调用closesocket函数关闭蓝牙套接字,并且确保使用CloseHandle函数释放套接字。
closesocket(client_socket);
CloseHandle ((LPVOID)client_socket);
6.    要结束对Winsock服务的使用,调用WSACleanup函数。在程序中对每个成功调用的WSAStartup都必须对应地调用WSACleanup
To create a server socket
1.      提供Winsock的版本和实现细节的数据来初始化caller application。可以通过调用WSAStartup函数来获得这个数据。
WSADATA wsd;
WSAStartup (MAKEWORD(1,0), &wsd);
2.      调用socket函数来创建一个蓝牙套接字。
SOCKET server_socket = socket (AF_BT, SOCK_STREAM, BTHPROTO_RFCOMM);
socket函数的参数值将套接字设置为蓝牙服务。
3.      通过设置SOCKADDR_BTH结构体来储存服务器设备的信息。
SOCKADDR_BTH sa;
memset (&sa, 0, sizeof(sa));
sa.addressFamily = AF_BT;
sa.port = channel & 0xff;
注意   为了避免冲突,在选择服务器通道时建议将channel设置为0,这样RFCOMM将自动使用下一个有效的通道。
结构体中的信息用来将套接字绑定到服务器设备的本地地址上。
4.      调用bind函数绑定第二步中创建的server_socket,传入第三步中创建的sa的引用指定设备信息。
if (bind (server_socket, (SOCKADDR *)&sa, sizeof(sa)))
{
 ... //Perform error handling
 closesocket (server_socket);
 return 0;
}
5.      listen函数来监听客户端蓝牙设备发送的连接请求。
if (listen (server_socket, 5))
{
 ... //Perform error handling
 closesocket (server_socket);
 return 0;
}
6.      accept函数来接受传入的连接请求。
SOCKADDR_BTH sa2;
int size = sizeof(sa2);
SOCKET s2 = accept (server_socket, (SOCKADDR *)&sa2, &size);
调用accept将返回SCOKADDR_BTH类型的客户端地址。
7.      调用closecocket函数来关闭套接字。
closesocket(server_socket);

要结束对Winsock服务的使用,调用WSACleanup函数。在程序中对每个成功调用的WSAStartup都必须对应地调用WSACleanup





原创粉丝点击