用于服务发现的蓝牙和 WSALookupServiceBegin

要发现蓝牙服务器上是否存在特定服务,客户端需要使用 WSALookupServiceBeginWSALookupServiceNextWSALookupServiceEnd 函数。 可以对本地和远程地址进行查询,但只能与远程地址建立连接。 在此操作中发现的服务句柄不能用于通过 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。

下表列出的标志用于 WSALookupServiceBeginWSALookupServiceNext 函数的 dwControlFlags 参数,以控制查询结果。 LUP_CONTAINERSLUP_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 结构的所有其他成员都将被忽略。

WSALookupServiceBegindwControlFlags 参数中传递以下标志,以控制高级查询的结果。

标记 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,随后调用 WSALookupServiceNextlpBlob 中的结果是一个蓝牙 SDP 句柄数组。 对于 SDP_SERVICE_ATTRIBUTE_REQUESTSDP_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_REQUESTSDP_SERVICE_ATTRIBUTE_REQUESTSDP_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_REQUESTSDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST 二进制蓝牙 SDP 记录。 对于 SDP_SERVICE_ATTRIBUTE_REQUEST,所有结果都会在对 WSALookupServiceNext 函数的一次调用中返回。

注意

如果在服务查询的输入过程中未指定 lpBlob 成员,则会对 lpServiceClassId 成员中指定的服务执行服务和属性搜索,属性范围从 0 到 0xFFFF。

用于服务查询的蓝牙和 WSAQUERYSET

发现蓝牙设备和服务

蓝牙和 WSALookupServiceNext

用于设备查询的蓝牙和 WSALookupServiceBegin

BTH_QUERY_SERVICE

connect

SOCKADDR_BTH

WSAAddressToString

WSALookupServiceBegin

WSALookupServiceEnd

WSALookupServiceNext

WSAQUERYSET

Windows 套接字