c++中蓝牙编程的库类

头文件.h
#pragma once
#ifndef NS_BTH
#include "ws2bth.h"	//如果没有定义NS_BTH宏,则将PSDK头文件包含进来
#endif

// for WSALookupServiceBegin() WSALookupServiceNext etc.
#include 
#pragma comment(lib,"ws2_32.lib")
#include 

// for BluetoothFindFirstDevice() BluetoothFindNextDevice() etc.
#include 
#include 
#pragma comment ( lib, "Irprops.lib")

#ifndef BTH_ADDR
typedef ULONGLONG BTH_ADDR;
#endif

#ifndef SAFE_DELETE
#define SAFE_DELETE(pObj) {if(pObj) delete pObj; pObj = NULL;}
#endif

#ifndef SAFE_DELETERG
#define SAFE_DELETERG(pObj) {if(pObj) delete [] pObj; pObj = NULL;}
#endif

#define RECEIVE_OVER_COMMAND	0x00001000

typedef struct _tag_BthDev_Info
{
	BTH_ADDR btAddr;
	TCHAR szAddr[32];
	TCHAR szName[128];

	_tag_BthDev_Info()
	{
		memset(this, 0, sizeof(this));
	}
}
BTHDEV_INFO;

class CGGBlueTooth
{
public:
	CGGBlueTooth();
	~CGGBlueTooth();

	BOOL StartSearchBthDev(IN DWORD dwControlFlags);
	BOOL GetNextBthDev(
		IN OUT BTHDEV_INFO *pcBthDevInfo,
		IN DWORD dwControlFlags = LUP_RETURN_NAME | LUP_RETURN_ADDR | LUP_FLUSHCACHE
		);
	BOOL EndSearchBthDev();

	//Socket Api
	BOOL Create(int af = AF_BTH, int type = SOCK_STREAM, int protocol = BTHPROTO_RFCOMM);
	BOOL Close();

	//If no error occurs, this function returns zero. If an error occurs, it returns SOCKET_ERROR
	int Bind(BTH_ADDR sktAddr = 0, ULONG port = BT_PORT_ANY);
	int Listen(IN int backlog);
	int GetSockName(BTH_ADDR *psktAddr, ULONG *port);
	int SetBthService(TCHAR *lpServiceName);
	int Accept(CGGBlueTooth *pcBth);
	int Connect(BTH_ADDR sktAddr, ULONG port, int nMSecond = -1);
	int Send(LPVOID lpData, int len, int flags = 0);
	int Recv(LPVOID lpData, int len, int flags = 0);
	int SendAll(LPVOID lpData, int len, int flags = 0);
	int RecvAll(LPVOID lpData, int len, int flags = 0);

private:
	void HexMac2String(BTH_ADDR dw64Addr, TCHAR *pstrMac);

private:
	HANDLE m_hLookup;
	SOCKET m_hSocket;
	SOCKADDR_BTH m_sktAddr;
};


====================================================================================================================

源文件.cpp

#include "stdafx.h"
#include "GGBlueTooth.h"
//#include "tchar.h"

CGGBlueTooth::CGGBlueTooth()
: m_hLookup(NULL)
, m_hSocket(NULL)
{
	memset(&m_sktAddr, 0, sizeof(m_sktAddr));
}

CGGBlueTooth::~CGGBlueTooth()
{
	EndSearchBthDev();
	Close();
}

void CGGBlueTooth::HexMac2String(BTH_ADDR dw64Addr, TCHAR *pstrMac)
{
	BYTE *pbAddr = (BYTE*)&dw64Addr;

	_stprintf(
		pstrMac, _T("%02X:%02X:%02X:%02X:%02X:%02X"),
		pbAddr[5], pbAddr[4], pbAddr[3],
		pbAddr[2], pbAddr[1], pbAddr[0]
		);
}

BOOL CGGBlueTooth::StartSearchBthDev(IN DWORD dwControlFlags)
{
	WSAQUERYSET wsaq;
	ZeroMemory(&wsaq, sizeof(wsaq));
	wsaq.dwSize = sizeof(wsaq);
	wsaq.dwNameSpace = NS_BTH;
	wsaq.lpcsaBuffer = NULL;

	return WSALookupServiceBegin(&wsaq, dwControlFlags, &m_hLookup) == ERROR_SUCCESS ? TRUE : FALSE;
}

BOOL CGGBlueTooth::GetNextBthDev(
	IN OUT BTHDEV_INFO *pcBthDevInfo,
	IN DWORD dwControlFlags /* = LUP_RETURN_NAME | LUP_RETURN_ADDR | LUP_FLUSHCACHE*/
	)
{
	if (!m_hLookup || !pcBthDevInfo)
	{
		return FALSE;
	}

	memset(pcBthDevInfo->szAddr, 0, sizeof(pcBthDevInfo->szAddr));
	memset(pcBthDevInfo->szName, 0, sizeof(pcBthDevInfo->szName));

	union
	{
		CHAR buf[5000];
		double __unused; // ensure proper alignment
	};
	LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET)buf;
	DWORD dwSize = sizeof(buf);
	int nResult;

	ZeroMemory(pwsaResults, sizeof(WSAQUERYSET));
	pwsaResults->dwSize = sizeof(WSAQUERYSET);
	pwsaResults->dwNameSpace = NS_BTH;
	pwsaResults->lpBlob = NULL;

	nResult = WSALookupServiceNext(m_hLookup, dwControlFlags, &dwSize, pwsaResults);
	if (nResult == ERROR_SUCCESS)
	{
		pcBthDevInfo->btAddr = ((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr;
		BOOL bHaveName = pwsaResults->lpszServiceInstanceName && *(pwsaResults->lpszServiceInstanceName);

		if (bHaveName)
		{
			HexMac2String(pcBthDevInfo->btAddr, pcBthDevInfo->szAddr);
			_tcscpy(pcBthDevInfo->szName, pwsaResults->lpszServiceInstanceName);
		}
		return TRUE;
	}

	return FALSE;
}

BOOL CGGBlueTooth::EndSearchBthDev()
{
	if (m_hLookup)
	{
		WSALookupServiceEnd(m_hLookup);
		m_hLookup = NULL;
		return TRUE;
	}

	return FALSE;
}

///===============================

BOOL CGGBlueTooth::Create(int af/* = AF_BTH*/, int type/* = SOCK_STREAM*/, int protocol/* = BTHPROTO_RFCOMM*/)
{
	if (m_hSocket)
	{
		return FALSE;
	}

	m_hSocket = socket(af, type, protocol);
	m_sktAddr.addressFamily = af;
	m_sktAddr.serviceClassId = GUID_NULL;
	return m_hSocket == INVALID_SOCKET ? FALSE : TRUE;
}

BOOL CGGBlueTooth::Close()
{
	if (m_hSocket)
	{
		closesocket(m_hSocket);
		return TRUE;
	}
	return FALSE;
}

int CGGBlueTooth::Bind(BTH_ADDR sktAddr/* = 0*/, ULONG port/* = BT_PORT_ANY*/)
{
	m_sktAddr.btAddr = sktAddr;
	m_sktAddr.port = port;
	return bind(m_hSocket, (SOCKADDR *)&m_sktAddr, sizeof(m_sktAddr));
}

int CGGBlueTooth::Listen(int backlog)
{
	return listen(m_hSocket, backlog);
}

int CGGBlueTooth::GetSockName(BTH_ADDR *psktAddr, ULONG *port)
{
	int nLen = sizeof(m_sktAddr);
	int nResult = getsockname(m_hSocket, (SOCKADDR *)&m_sktAddr, &nLen);
	if (nResult == 0)
	{
		*psktAddr = m_sktAddr.btAddr;
		*port = m_sktAddr.port;
	}
	return nResult;
}

GUID OBEXFileTransferServiceClass_UUID_EX = { 0x00001106, 0x0000, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
int CGGBlueTooth::SetBthService(TCHAR * lpServiceName)
{
	CSADDR_INFO sockInfo;
	sockInfo.iProtocol = BTHPROTO_RFCOMM;
	sockInfo.iSocketType = SOCK_STREAM;
	sockInfo.LocalAddr.lpSockaddr = (SOCKADDR *)&m_sktAddr;
	sockInfo.LocalAddr.iSockaddrLength = sizeof(m_sktAddr);
	sockInfo.RemoteAddr.lpSockaddr = (SOCKADDR *)&m_sktAddr;
	sockInfo.RemoteAddr.iSockaddrLength = sizeof(m_sktAddr);

	WSAQUERYSET svcInfo = { 0 };
	svcInfo.dwSize = sizeof(svcInfo);
	svcInfo.dwNameSpace = NS_BTH;
	svcInfo.lpszServiceInstanceName = lpServiceName;
	svcInfo.lpServiceClassId = &OBEXFileTransferServiceClass_UUID_EX;
	svcInfo.dwNumberOfCsAddrs = 1;
	svcInfo.lpcsaBuffer = &sockInfo;

	return WSASetService(&svcInfo, RNRSERVICE_REGISTER, 0);
}

int CGGBlueTooth::Accept(CGGBlueTooth *pcBth)
{
	SOCKADDR_BTH ca;
	int size = sizeof(ca);
	pcBth->m_hSocket = accept(m_hSocket, (SOCKADDR *)&ca, &size);
	pcBth->m_sktAddr = ca;
	return pcBth->m_hSocket == INVALID_SOCKET ? SOCKET_ERROR : 0;
}

int CGGBlueTooth::Connect(BTH_ADDR sktAddr, ULONG port, int nMSecond/* = -1*/)
{
	SOCKADDR_BTH sa = { 0 };
	sa.addressFamily = AF_BTH;
	sa.btAddr = sktAddr;
	sa.port = port;

	if (nMSecond == -1)
	{
		return connect(m_hSocket, (LPSOCKADDR)&sa, sizeof(SOCKADDR_BTH));
	}

	ULONG non_blocking = 1;
	ULONG blocking = 0;

	int nResult = ioctlsocket(m_hSocket, FIONBIO, &non_blocking);
	if (nResult == SOCKET_ERROR)
	{
		return nResult;
	}

	nResult = SOCKET_ERROR;
	if (connect(m_hSocket, (LPSOCKADDR)&sa, sizeof(SOCKADDR_BTH)) == SOCKET_ERROR)
	{
		struct timeval tv;
		fd_set writefds;

		// 设置连接超时时间
		tv.tv_sec = nMSecond / 1000; // 秒数
		tv.tv_usec = nMSecond % 1000; // 毫秒

		FD_ZERO(&writefds);
		FD_SET(m_hSocket, &writefds);

		nResult = select((int)m_hSocket + 1, NULL, &writefds, NULL, &tv);
		if (nResult > 0)
		{
			if (FD_ISSET(m_hSocket, &writefds))
			{
				int error = 0;
				int len = sizeof(error);
				//下面的一句一定要,主要针对防火墙 
				if (!(getsockopt(m_hSocket, SOL_SOCKET, SO_ERROR, (char *)&error, &len) != 0 || error != 0))
				{
					nResult = 0;
				}
			}
		}
		else if (nResult == 0)
		{
			nResult = -2;
		}
	}

	if (ioctlsocket(m_hSocket, FIONBIO, &blocking) == SOCKET_ERROR)
	{
		nResult = SOCKET_ERROR;
	}
	return nResult;
}

int CGGBlueTooth::Send(LPVOID lpData, int len, int flags/* = 0*/)
{
	return send(m_hSocket, (char *)lpData, len, flags);
}

int CGGBlueTooth::Recv(LPVOID lpData, int len, int flags/* = 0*/)
{
	return recv(m_hSocket, (char *)lpData, len, flags);
}

int CGGBlueTooth::SendAll(LPVOID lpData, int len, int flags/* = 0*/)
{
	int nCount = send(m_hSocket, (char *)lpData, len, flags);
	if (nCount == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
	{
		return SOCKET_ERROR;
	}

	int nCommand = 0;
	nCount = recv(m_hSocket, (char *)&nCommand, 4, flags);
	if (nCount != 4 || nCommand != RECEIVE_OVER_COMMAND)
	{
		return SOCKET_ERROR;
	}

	return ERROR_SUCCESS;
}

int CGGBlueTooth::RecvAll(LPVOID lpData, int len, int flags/* = 0*/)
{
	int nCount = -1, nCurRecv = 0, nMaxRead = 32 * 1024;

	while (nCurRecv < len)
	{
		if (len - nCurRecv < nMaxRead)
		{
			nMaxRead = len - nCurRecv;
		}

		nCount = recv(m_hSocket, (char *)lpData + nCurRecv, nMaxRead, flags);

		if (nCount == SOCKET_ERROR)
		{
			if (WSAGetLastError() == WSAEWOULDBLOCK)
			{
				Sleep(1);
				continue;
			}
			else
			{
				return SOCKET_ERROR;
			}
		}

		nCurRecv += nCount;
	}

	int nCommand = RECEIVE_OVER_COMMAND;
	nCount = send(m_hSocket, (char *)&nCommand, 4, flags);
	if (nCount == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
	{
		return SOCKET_ERROR;
	}

	return ERROR_SUCCESS;
}


你可能感兴趣的:(【蓝牙】)