用于服务发现的蓝牙和 WSALookupServiceBegin
要发现蓝牙服务器上是否存在特定服务,客户端需要使用 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 Sockets connect 函数调用时,使用 SOCKADDR_BTH 结构的 serviceClassId 成员指定要连接的服务类别 UUID。
下表列出的标志用于 WSALookupServiceBegin 和 WSALookupServiceNext 函数的 dwControlFlags 参数,以控制查询结果。 LUP_CONTAINERS 和 LUP_FLUSHCACHE 标志用于 WSALookupServiceBegin 函数;其余标志用于调用 WSALookupServiceNext 函数。
标记 | Result |
---|---|
LUP_CONTAINERS | 不可设置。 |
LUP_FLUSHCACHE | 应用程序通常应指定 LUP_FLUSHCACHE。 此标志指示系统忽略任何缓存信息,并与指定设备建立无线 SDP 连接以执行 SDP 搜索。 此非缓存操作可能需要几秒钟(而缓存搜索则会快速返回)。 蓝牙目前不会主动缓存附近设备的 SDP 记录,也不会主动缓存以前的查询。 因此,如果未指定 LUP_FLUSHCACHE,应用程序应预计查询可能不会返回任何结果(错误代码为 WSASERVICE_NOT_FOUND)。 使用 Windows Sockets 接口提供的缓存数据今后可能会得到增强。 |
LUP_RES_SERVICE | 返回有关本地蓝牙地址的信息。 只有还指定了 LUP_RETURN_ADDR 时,此标志才有效。 |
LUP_RETURN_NAME | 每次调用 WSALookupServiceNext 函数时,都会返回 WSAQUERYSET 结构的 lpszServiceInstanceName 成员中的服务显示名称。 |
LUP_RETURN_TYPE | 返回 WSAQUERYSET 结构的 lpServiceClassId 成员中的服务类别 ID。 注意:此标志仅适用于 WSALookupServiceBegin 函数。 对于 WSALookupServiceNext,此值始终为零。 |
LUP_RETURN_ADDR | 返回与 connect 函数调用配合使用的 lpcsaBuffer 成员中的地址。 返回的地址包含端口号。 |
LUP_RETURN_BLOB | 返回 lpBlob 成员中匹配的 SD 记录,格式符合蓝牙 SDP 记录规范。 |
LUP_RETURN_ALL | 返回上述所有标志的信息。 |
LUP_RETURN_COMMENT | 每次调用 WSALookupServiceNext 函数时,都会返回 WSAQUERYSET 结构的 lpszComment 成员中的服务描述。 |
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 参数中传递以下标志,以控制高级查询的结果。
标记 | Result |
---|---|
LUP_CONTAINERS | 不可设置。 |
LUP_FLUSHCACHE | 应用程序通常应指定 LUP_FLUSHCACHE。 此标志指示系统忽略任何缓存信息,并与指定设备建立无线 SDP 连接以执行 SDP 搜索。 此非缓存操作可能需要几秒钟(而缓存搜索则会快速返回)。 蓝牙不会主动缓存附近设备的 SDP 记录,也不会主动缓存以前的查询。 因此,如果未指定 LUP_FLUSHCACHE,应用程序应预计查询可能会经常返回无结果 (WSASERVICE_NOT_FOUND)。 使用 Windows Sockets 接口提供的缓存数据今后可能会得到增强。 |
LUP_RES_SERVICE | 返回本地蓝牙地址的信息。 只有同时指定 LUP_RETURN_ADDRR 时,设置该标志才会生效。 |
LUP_RETURN_NAME | 返回该服务的显示名称。 对于 SDP_SERVICE_SEARCH_REQUEST,此标志将被忽略。 |
LUP_RETURN_TYPE | 返回服务类 ID。 对于 SDP_SERVICE_SEARCH_REQUEST,此标志将被忽略。 |
LUP_RETURN_ADDR | 返回与 connect 函数调用配合使用的 lpcsaBuffer 成员中的地址。 返回的地址包含端口号。 对于 SDP_SERVICE_SEARCH_REQUEST,此标志将被忽略。 |
LUP_RETURN_BLOB | 以符合蓝牙 SDP 记录规范的格式返回匹配的 SD 记录。 对于 SDP_SERVICE_SEARCH_REQUEST,随后调用 WSALookupServiceNext 时 lpBlob 中的结果是一个蓝牙 SDP 句柄数组。 对于 SDP_SERVICE_ATTRIBUTE_REQUEST 和 SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST,对 WSALookupServiceNext 的每次后续调用的结果都是二进制蓝牙 SDP 记录,其属性仅限于查询的 pRange 成员指定的属性。 SDP_SERVICE_SEARCH_REQUEST 需要使用此标记。 |
LUP_RETURN_COMMENT | 每次调用 WSALookupServiceNext 函数时,都会返回 WSAQUERYSET 结构的 lpszComment 成员中的服务描述。 |
LUP_FLUSHPREVIOUS | 跳过下一条可用记录,并返回其后的记录。 |
在输入时,lpBlob->pBlobData 指向一个包含下表所列值的 BTH_QUERY_SERVICE 结构。
注意
初始搜索请求必须能够放入一个 L2CAP 数据包中。 但是,响应可能会被分成许多 L2CAP 数据包。
成员 | Value |
---|---|
type | 要执行的搜索类型。 此值可以是 SDP_SERVICE_SEARCH_REQUEST、SDP_SERVICE_ATTRIBUTE_REQUEST 或 SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST 之一。 每种搜索类型都与蓝牙 SDP 规范定义的底层搜索机制相关联。 每次返回的结果都是本节(高级服务查询)前面定义的 WSAQUERYSET 结构所描述的形式。 |
serviceHandle | 用于属性搜索。 此值用于指定服务句柄,以便查询 pRange 成员中的属性。 |
uuids | 用于服务和 serviceAttribute 搜索。 此值指定了记录必须包含的 UUID 以匹配搜索。 如果要查询的 UUID 少于 MAX_UUIDS_IN_QUERY,则此值会将紧随最后一个有效 UUID 之后的 SdpQueryUuid 元素设置为全零。 |
numRange | 用于属性和 serviceAttribute 搜索。 此值指定 pRange 中的元素个数。 |
pRange | 用于属性和 serviceAttribute 搜索。 此值指定要检索的任何匹配记录的属性值。 |
每次成功调用 WSALookupServiceNext 函数后,lpBlob->pBlobData 都会指向一个数据块,其中包含下表列出的值。
值 | 说明 |
---|---|
SDP_SERVICE_SEARCH_REQUEST | 与蓝牙 1.1 SDP 4.5.2 中定义的 ServiceRecordHandleList 相同的 SDP 记录句柄数组。 返回的 SDP 句柄数按 (lpBlob->cbSize)/sizeof(ULONG) 计算。 所有结果都会在对 WSALookupServiceNext 函数的一次调用中返回。 |
SDP_SERVICE_ATTRIBUTE_REQUEST 或 SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST | 二进制蓝牙 SDP 记录。 对于 SDP_SERVICE_ATTRIBUTE_REQUEST,所有结果都会在对 WSALookupServiceNext 函数的一次调用中返回。 |
注意
如果在服务查询的输入过程中未指定 lpBlob 成员,则会对 lpServiceClassId 成员中指定的服务执行服务和属性搜索,属性范围从 0 到 0xFFFF。