关于使用c++制作蓝牙连接,Windows版本
1 #define _CRT_SECURE_NO_WARNINGS 2 #pragma warning(disable : 4995) 3 #include <iostream> 4 #include <string> 5 #include <vector> 6 #include <sstream> 7 #include <iomanip> 8 #include <windows.h> 9 #include <stdlib.h> 10 #include<bluetoothapis.h> 11 #include <winsock.h> 12 #include <ws2bth.h> 13 #include<Stringapiset.h> 14 #pragma comment(lib, "wsock32.lib") 15 #pragma comment(lib, "bthprops.lib") 16 #pragma comment(lib,"ws2_32.lib") 17 using namespace std; string PassKey; 18 HANDLE btdi; 19 vector<BLUETOOTH_DEVICE_INFO> devices; 20 BLUETOOTH_DEVICE_INFO device; 21 SOCKET sockClient; 22 WSADATA wsaData; 23 string wstring2string(const wstring& ws) 24 { 25 string curLocale = setlocale(LC_ALL, NULL); 26 setlocale(LC_ALL, "chs"); 27 const wchar_t* _Source = ws.c_str(); 28 size_t _Dsize = 2 * ws.size() + 1; 29 char* _Dest = new char[_Dsize]; 30 memset(_Dest, 0, _Dsize); 31 wcstombs(_Dest, _Source, _Dsize); 32 string result = _Dest; delete[]_Dest; 33 setlocale(LC_ALL, curLocale.c_str()); 34 return result; 35 } 36 string String_To_UTF8(const std::string& str) 37 { 38 int nwLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0); 39 wchar_t* pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然会出现尾巴 40 ZeroMemory(pwBuf, nwLen * 2 + 2); 41 ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen); 42 int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL); char* pBuf = new char[nLen + 1]; 43 ZeroMemory(pBuf, nLen + 1); 44 ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL); 45 std::string retStr(pBuf); delete[]pwBuf; delete[]pBuf; 46 pwBuf = NULL; pBuf = NULL; return retStr; 47 } 48 string getMAC(BLUETOOTH_ADDRESS Daddress) 49 { 50 /*string addr; addr = addr.sprintf("%02x:%02x:%02x:%02x:%02x:%02x", Daddress.rgBytes[5], Daddress.rgBytes[4], Daddress.rgBytes[3], Daddress.rgBytes[2], Daddress.rgBytes[1], Daddress.rgBytes[0]); 51 return addr;*/ 52 ostringstream oss; oss << hex << setfill('0') << uppercase; 53 for (int i = 5; i >= 0; --i) { 54 oss << setw(2) << static_cast<int>(Daddress.rgBytes[i]); if (i > 0) { oss << ":"; } } 55 return oss.str(); 56 } 57 vector<BLUETOOTH_DEVICE_INFO> scanDevices() 58 { 59 HBLUETOOTH_RADIO_FIND hbf = NULL; 60 HANDLE hbr = NULL; HBLUETOOTH_DEVICE_FIND hbdf = NULL; 61 BLUETOOTH_FIND_RADIO_PARAMS btfrp = { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) }; //调用BluetoothFindFirstDevice搜索本机蓝牙收发器所需要的搜索参数对象 62 BLUETOOTH_RADIO_INFO bri = { sizeof(BLUETOOTH_RADIO_INFO) }; //初始化一个储存蓝牙收发器信息(BLUETOOTH_RADIO_INFO)的对象bri 63 BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = { sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS) };//调用BluetoothFindFirstDevice搜索本所需要的搜索参数对象 64 BLUETOOTH_DEVICE_INFO btdi = { sizeof(BLUETOOTH_DEVICE_INFO) }; //初始化一个远程蓝牙设备信息(BLUETOOTH_DEVICE_INFO)对象btdi,以储存搜索到的蓝牙设备信息 65 hbf = BluetoothFindFirstRadio(&btfrp, &hbr); //得到第一个被枚举的蓝牙收发器的句柄hbf可用于BluetoothFindNextRadio,hbr可用于BluetoothFindFirstDevice。若没有找到本机的蓝牙收发器,则得到的句柄hbf=NULL 66 vector<BLUETOOTH_DEVICE_INFO> res; bool brfind = hbf != NULL; 67 while (brfind) { if (BluetoothGetRadioInfo(hbr, &bri) == ERROR_SUCCESS)//获取蓝牙收发器的信息,储存在bri中 68 { 69 cout << "[Local Device Name]:" << wstring2string(bri.szName) << "\t"; //蓝牙收发器的名字 70 cout << "[Local Device Address]: " << getMAC(bri.address) << endl; 71 cout << "------------------------蓝牙扫描结果如下----------------------------" << endl; 72 btsp.hRadio = hbr; //设置执行搜索设备所在的句柄,应设为执行BluetoothFindFirstRadio函数所得到的句柄 73 btsp.fReturnAuthenticated = TRUE;//是否搜索已配对的设备 btsp.fReturnConnected = FALSE;//是否搜索已连接的设备 74 btsp.fReturnRemembered = TRUE;//是否搜索已记忆的设备 75 btsp.fReturnUnknown = TRUE;//是否搜索未知设备 76 btsp.fIssueInquiry = TRUE;//是否重新搜索,True的时候会执行新的搜索,时间较长,FALSE的时候会直接返回上次的搜索结果。 77 btsp.cTimeoutMultiplier = 30;//指示查询超时的值,以1.28秒为增量。 例如,12.8秒的查询的cTimeoutMultiplier值为10.此成员的最大值为48.当使用大于48的值时,调用函数立即失败并返回 78 hbdf = BluetoothFindFirstDevice(&btsp, &btdi);//通过找到第一个设备得到的HBLUETOOTH_DEVICE_FIND句柄hbdf来枚举远程蓝牙设备,搜到的第一个远程蓝牙设备的信息储存在btdi对象中。若没有远程蓝牙设备,hdbf=NULL。 79 bool bfind = hbdf != NULL; 80 int i = 0; 81 while (bfind) { 82 cout << ++i << " " << "[Name]:" << wstring2string(btdi.szName); //远程蓝牙设备的名字 83 cout << "\t[Address]:" << getMAC(btdi.Address) << endl; 84 res.push_back(btdi); bfind = BluetoothFindNextDevice(hbdf, &btdi);//通过BluetoothFindFirstDevice得到的HBLUETOOTH_DEVICE_FIND句柄来枚举搜索下一个远程蓝牙设备,并将远程蓝牙设备的信息储存在btdi中 } 85 BluetoothFindDeviceClose(hbdf);//使用完后记得关闭HBLUETOOTH_DEVICE_FIND句柄hbdf。 } 86 CloseHandle(hbr); 87 brfind = BluetoothFindNextRadio(hbf, &hbr);//通过BluetoothFindFirstRadio得到的HBLUETOOTH_RADIO_FIND句柄hbf来枚举搜索下一个本地蓝牙收发器,得到可用于BluetoothFindFirstDevice的句柄hbr。 } 88 return res; 89 } 90 void setPassKey() { cout << "请输入配对码:(如果不知道请输入默认0000):"; cin >> PassKey; cout << "您输入的配对码为: " << PassKey << endl; } 91 bool pairDevice() 92 { 93 cout << "输入你想要配对的设备的序号:"; 94 int index; cin >> index; //获取设备信息 device = devices[index - 1]; //输入配对码 95 setPassKey(); //string转PWSTR wstringstream wss; for (char c : PassKey) { wss << wchar_t(c); } wstring wstr = wss.str(); const wchar_t* wcharPtr = wstr.c_str(); PWSTR AUTHENTICATION_PASSKEY = const_cast<PWSTR>(wcharPtr); //开始配对 wstring ws = device.szName; HBLUETOOTH_AUTHENTICATION_REGISTRATION hCallbackHandle = 0; DWORD result = -1; 96 if (!device.fAuthenticated) { 97 result = BluetoothAuthenticateDevice(NULL, btdi, &device, AUTHENTICATION_PASSKEY, (ULONG)wcslen(AUTHENTICATION_PASSKEY)); //配对函数,AUTHENTICATION_PASSKEY是我的蓝牙配对码 98 if (result != ERROR_SUCCESS) { 99 switch (result) { case ERROR_CANCELLED: 100 cout << "用户取消了身份验证或配对操作" << endl; break; case ERROR_INVALID_PARAMETER: cout << "传递给函数的参数无效" << endl; break; 101 case ERROR_NO_MORE_ITEMS: cout << "没有更多的设备可以配对" << endl; break; case ERROR_NOT_SUPPORTED: cout << "不支持请求的操作" << endl; break; 102 case ERROR_GEN_FAILURE: cout << "通用失败错误" << endl; break; 103 case ERROR_BUSY: cout << "蓝牙堆栈忙" << endl; break; 104 case ERROR_TIMEOUT: cout << "操作超时" << endl; break; case ERROR_DEVICE_NOT_CONNECTED: cout << "蓝牙设备未连接" << endl; break; 105 case ERROR_DEVICE_NOT_AVAILABLE: cout << "设备不可用" << endl; break; 106 default: cout << "校验码出错,请手动进行设备连接" << endl; break; } return false; } 107 } 108 cout << "身份验证成功,蓝牙设备已成功配对" << endl;; BluetoothUpdateDeviceRecord(&device); return true; 109 } 110 bool sendMessage(SOCKET sockClient, string message, int& iCount) { 111 int sum = 0; while (iCount < message.size()) 112 { 113 string utf8message = String_To_UTF8(message); iCount = send(sockClient, utf8message.data() + sum, utf8message.size() - sum, 0); 114 if (iCount == SOCKET_ERROR) { cout << "发送失败" << endl; return false; } sum += iCount; } } 115 bool buildConnect(BLUETOOTH_DEVICE_INFO device, SOCKET& sockClient) { 116 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { 117 cout << "Winsock库初始化失败" << endl; 118 return FALSE; 119 } 120 SOCKET client_socket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); 121 if (client_socket == INVALID_SOCKET) 122 { 123 cout << "套接字创建失败" << endl; WSACleanup(); return FALSE; } 124 sockClient = client_socket; SOCKADDR_BTH serverAddress; memset(&serverAddress, 0, sizeof(serverAddress)); 125 serverAddress.addressFamily = AF_BTH; BTH_ADDR deviceAddress = device.Address.ullLong; serverAddress.btAddr = deviceAddress; serverAddress.port = 0; 126 serverAddress.serviceClassId = SerialPortServiceClass_UUID; 127 int err = ::connect(client_socket, (SOCKADDR*)&serverAddress, sizeof(serverAddress)); if (0 == err) { } else { cout << "connect连接失败" << endl; 128 closesocket(client_socket); WSACleanup(); return FALSE; } while (true) { cout << "选择您的操作:1.发送信息 2.退出" << endl; int choice; cin >> choice; 129 if (choice == 1) { cout << "请输入您想要发送的信息:"; string message; cin >> message; int iCount = 0; 130 if (sendMessage(client_socket, message, iCount)) { 131 cout << "信息传输成功,发送字符数:" << iCount << endl; 132 } else { 133 cout << "send失败" << endl; return false; } } 134 else if (choice == 2) { break; } else { 135 cout << "输入错误,请重新输入" << endl; 136 } 137 } 138 closesocket(client_socket); WSACleanup(); 139 BluetoothUpdateDeviceRecord(&device); 140 return TRUE; } 141 void main() { 142 devices = scanDevices(); 143 if (pairDevice()) { 144 buildConnect(device, sockClient); 145 } 146 return; 147 }