蓝牙和 WSALookupServiceBegin for Service Discovery
为了发现蓝牙服务器上存在特定服务,客户端使用 WSALookupServiceBegin、WSALookupServiceNext,以及 WSALookupServiceEnd 函数。 可以针对本地和远程地址执行查询,但只能使用远程地址建立连接。 在此作期间发现的服务句柄不能用于通过 WSASetService删除服务。 RFCOMM 不支持环回。
可以执行两种基本类型的服务发现查询:
- 在本地设备上查询一个或多个服务
- 在指定的对等设备上查询一个或多个服务
WSALookupServiceBegin 函数在其 lpqsRestrictions 参数中接收 WSAQUERYSET 结构。 WSALookupServiceBegin 基于 WSAQUERYSET 包含的一组搜索限制执行客户端查询。 使用 WSALookupServiceBegin 函数查询服务时,蓝牙客户端必须指定下表中列出的限制,在 WSAQUERYSET 结构中。
WSAQUERYSET 成员 | 限制 |
---|---|
dwSize | 设置为 sizeof(WSAQUERYSET)。 |
lpServiceClassId | 设置为最具体的蓝牙 UUID,可用于确定查询的范围。 例如,将 lpServiceClassId 设置为 L2CAP 协议的 UUID 会导致返回所有 L2CAP 服务,实质上枚举目标上的所有 SD 记录。 但是,将 UUID 设置为特定服务仅返回该服务的实例。 |
dwNameSpace | 设置为 NS_BTH。 |
dwNumberOfCsAddrs | 设置为 0。 |
lpszContext | 设置为用于建立 SDP 连接的蓝牙设备地址,以执行服务的查询。 此成员必须是使用 WSAAddressToString 函数转换的字符串。 如果提供了本地无线电地址,则会搜索本地 SDP 记录。 |
其他成员 | 将忽略 WSAQUERYSET 结构中的所有其他成员。 |
WSALookupServiceBegin 函数完成服务查询后,与远程设备的 SDP 连接不会保持活动状态;连接在 WSALookupServiceBegin 返回之前终止。 在服务查询完成后,要求 SDP 连接保持活动状态的应用程序应在发出 Windows 套接字 连接 函数调用时,使用 SOCKADDR_BTH 结构的 serviceClassId 成员指定要连接到的服务类 UUID。
下表中列出的标志在 dwControlFlags 参数中使用 WSALookupServiceBegin 和 WSALookupServiceNext 函数来控制查询结果。 WSALookupServiceBegin 函数使用 LUP_CONTAINERS 和 LUP_FLUSHCACHE 标志;其余标志用于调用 WSALookupServiceNext 函数。
旗 | 结果 |
---|---|
LUP_CONTAINERS | 不能设置。 |
LUP_FLUSHCACHE | 应用程序通常应指定 LUP_FLUSHCACHE。 此标志指示系统忽略任何缓存的信息,并建立与指定设备的无线 SDP 连接以执行 SDP 搜索。 此非缓存作可能需要几秒钟(而缓存的搜索会快速返回)。 蓝牙当前不会主动缓存来自附近设备的 SDP 记录,也不主动缓存以前的查询。 因此,如果未指定 LUP_FLUSHCACHE,应用程序应预测查询可能不会返回任何结果(错误代码为 WSASERVICE_NOT_FOUND)。 将来可能会增强使用 Windows 套接字接口提供的缓存数据。 |
LUP_RES_SERVICE | 返回有关本地蓝牙地址的信息。 仅当同时指定 LUP_RETURN_ADDR 时,此标志才有效。 |
LUP_RETURN_NAME | 返回 lpszServiceInstanceNameWSAQUERYSET 结构中服务的显示名称,以便每次调用 WSALookupServiceNext 函数。 |
LUP_RETURN_TYPE | 返回 lpServiceClassIdWSAQUERYSET 结构的成员中的服务类 ID。
注意: 使用此标志仅适用于 WSALookupServiceBegin 函数。 对于 WSALookupServiceNext,此值始终为零。 |
LUP_RETURN_ADDR | 返回 lpcsaBuffer 成员中要与 连接 函数调用一起使用的地址。 返回的地址包含端口号。 |
LUP_RETURN_BLOB | 根据蓝牙 SDP 记录规范,返回 lpBlob 成员中的匹配 SD 记录。 |
LUP_RETURN_ALL | 返回上述所有标志的信息。 |
LUP_RETURN_COMMENT | 返回 lpszComment 成员 WSAQUERYSET 结构中的服务说明,以便每次调用 WSALookupServiceNext 函数。 |
LUP_FLUSHPREVIOUS | 跳过下一条可用记录,并返回后面的记录。 |
高级服务查询
上一节中所述的查询作可用于从单个 GUID 返回所有结果,这应该足以满足大多数应用程序的需求。 高级查询使应用程序能够创建更具体的查询;它提供匹配返回信息中的 UUID 和属性的功能。
若要对服务执行高级查询,蓝牙客户端必须在传递到 lpqsRestrictions 参数的 WSAQUERYSET 结构中指定以下限制。
WSAQUERYSET 成员 | 限制 |
---|---|
dwSize | 设置为 sizeof(WSAQUERYSET)。 |
lpszContext | 设置为用于建立 SDP 连接的蓝牙设备地址,以执行服务的查询。 此成员必须是使用 WSAAddressToString 函数转换的字符串。 如果提供了本地无线电地址,则会搜索本地 SDP 记录。 |
lpBlob.pBlobData | 指向包含限制查询结果的所有参数的 BTH_QUERY_SERVICE 结构的指针。 |
dwNameSpace | 设置为 NS_BTH。 |
其他成员 | 将忽略 WSAQUERYSET 结构中的所有其他成员。 |
以下标志在 WSALookupServiceBegin 的 dwControlFlags 参数中传递,以控制高级查询的结果。
旗 | 结果 |
---|---|
LUP_CONTAINERS | 不能设置。 |
LUP_FLUSHCACHE | 应用程序通常应指定 LUP_FLUSHCACHE。 此标志指示系统忽略任何缓存的信息,并建立与指定设备的无线 SDP 连接以执行 SDP 搜索。 此非缓存作可能需要几秒钟(而缓存的搜索会快速返回)。 蓝牙不会主动缓存来自附近设备的 SDP 记录,也不会主动缓存以前的查询。 因此,如果未指定 LUP_FLUSHCACHE,应用程序应期望查询经常不返回任何结果(WSASERVICE_NOT_FOUND)。 将来可能会增强使用 Windows 套接字接口提供的缓存数据。 |
LUP_RES_SERVICE | 返回本地蓝牙地址的信息。 仅当还指定了 LUP_RETURN_ADDRR 时,设置此标志才有效。 |
LUP_RETURN_NAME | 返回服务的显示名称。 对于 SDP_SERVICE_SEARCH_REQUEST,忽略此标志。 |
LUP_RETURN_TYPE | 返回服务类 ID。 对于 SDP_SERVICE_SEARCH_REQUEST,忽略此标志。 |
LUP_RETURN_ADDR | 返回 lpcsaBuffer 成员中要与 连接 函数调用一起使用的地址。 返回的地址包含端口号。 对于 SDP_SERVICE_SEARCH_REQUEST,忽略此标志。 |
LUP_RETURN_BLOB | 以符合蓝牙 SDP 记录规范的格式返回匹配的 SD 记录。 对于 SDP_SERVICE_SEARCH_REQUEST,后续调用 WSALookupServiceNext 的结果是蓝牙 SDP 句柄数组,lpBlob。 对于 SDP_SERVICE_ATTRIBUTE_REQUEST 和 SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST,对 WSALookupServiceNext 的每个后续调用的结果都是二进制蓝牙 SDP 记录,其属性限制为查询 pRange 成员指定的记录。 SDP_SERVICE_SEARCH_REQUEST需要此标志。 |
LUP_RETURN_COMMENT | 返回 lpszComment 成员 WSAQUERYSET 结构中的服务说明,以便每次调用 WSALookupServiceNext 函数。 |
LUP_FLUSHPREVIOUS | 跳过下一条可用记录,并返回后面的记录。 |
输入时,lpBlob->pBlobData 指向包含下表中列出的值的 BTH_QUERY_SERVICE 结构。
注意
初始搜索请求必须能够容纳到一个 L2CAP 数据包中。 但是,响应可能会分解成许多 L2CAP 数据包。
成员 | 价值 |
---|---|
类型 | 要执行的搜索类型。 此值可以是 SDP_SERVICE_SEARCH_REQUEST、SDP_SERVICE_ATTRIBUTE_REQUEST或 SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST之一。 每个搜索类型都与蓝牙 SDP 规范定义的底层搜索机制相关联。 每个返回结果都以 WSAQUERYSET 结构描述的形式返回,该结构在本(高级服务查询)部分前面定义。 |
serviceHandle | 用于属性搜索。 此值指定查询 pRange 成员中的属性的服务句柄。 |
uuids | 用于服务和 serviceAttribute 搜索。 此值指定记录必须包含的 UUID 以匹配搜索。 如果要查询小于 MAX_UUIDS_IN_QUERY UUID,则此值将紧跟最后一个有效 UUID 的 SdpQueryUuid 元素设置为所有零。 |
numRange | 用于属性和 serviceAttribute 搜索。 此值指定 pRange中的元素数。 |
pRange | 用于属性和 serviceAttribute 搜索。 此值指定要检索任何匹配记录的属性值。 |
每次成功调用 WSALookupServiceNext 函数后,lpBlob->pBlobData 指向包含下表中列出的值的一个数据块。
价值 | 描述 |
---|---|
SDP_SERVICE_SEARCH_REQUEST | SDP 记录句柄数组,该句柄与蓝牙 1.1 SDP 4.5.2 定义的 ServiceRecordHandleList 相同。 返回的 SDP 句柄数由 (lpBlob->cbSize) /sizeof(ULONG) 计算。 所有结果在对 WSALookupServiceNext 函数的单个调用中返回。 |
SDP_SERVICE_ATTRIBUTE_REQUEST 或 SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST | 二进制蓝牙 SDP 记录。 对于 SDP_SERVICE_ATTRIBUTE_REQUEST,所有结果在对 WSALookupServiceNext 函数的单个调用中返回。 |
注意
如果在服务查询的输入过程中未指定 lpBlob 成员,则会针对从 0 到 0xFFFF 的属性在 lpServiceClassId 成员中指定的服务执行服务和属性搜索。