1.      SDP

1.1       服务概述

SDP, Service Discovery Protocol,服务发现协议。

1.1.1    概念

SDP提供了一种用于发现服务及这些可用服务属性的方法,但它不提供利用这些服务的机制。其架构是Client-Server模式,如下图所示:

SDP Server维护了一个服务记录(Service Record)列表,每个条目包含了该服务的信息。 

SDP Client通过SDP request来向SDP Server获取服务记录信息

Client可以通过打开一条单独的连接来使用Server提供的某种服务

当Server的服务改变时,Client必须通过其他方式来了解这一信息,以便能够通过SDP来查询 。同时,当Server由于某种原因不可用时,Client可以使用SDP轮询Server 

当Server不再响应请求时,Client可以推断该Server不可用。

1.1.2   
服务记录(Service Record)

每一个Service用Service Record来表示。 

每一个Service Record由若干Service Attribute组成,如下图所示:

在SDP Server中,用Service Record Handle来唯一标识一个Service Record ,而Service Record Handle则使用32-bit数字表示。

在Service Record List中,Server使用0x00000000来表示SDP本身。

1.1.3   
服务属性(Service Attribute)

每个服务属性描述了一个服务的单个特征,实例如下:

一个服务属性包含了两个部分: 属性ID和属性值:

属性ID是16-bit无符号整型,用以区分Server中不同属性,属性ID还确定了相关的属性值的语义,属性值字段长度是可变的,由关联属性ID和服务记录类别决定。

1.1.4   
服务类(Service Class)

每个服务是一个服务类的实例 ,服务类定义了包含在该类服务记录的所有属性 

每个属性定义了指定的属性ID,及使用的属性值和属性值得格式 

服务记录包含了特定服务类及通用服务类的属性。

每个服务记录都包含一个唯一的ServiceClassIDList属性,该属性描述了本服务的服务类型。

每个服务类被分配了唯一的标识符 ,这个服务类标识符包含在ServiceClassIDList属性的属性值中,被称为UUID。

下面来看一个实例,下面这个SDP recored来源于ADK的sink例程中的SPP服务:

const uint8 spp_service_record
[SSP_SERVICE_RECORD_SIZE] =

{

0x09, 0x00, 0x01,           /* ServiceClassIDList(0x0001)
*/

0x35, 0x03,                 /* DataElSeq 3 bytes */

0x19, 0x11, 0x01,           /* UUID SerialPort(0x1101) */

0x09, 0x00, 0x04,           /* ProtocolDescriptorList(0x0004) */

0x35, 0x0c,                 /* DataElSeq 12 bytes */

0x35, 0x03,                 /* DataElSeq 3 bytes */

0x19, 0x01, 0x00,           /* UUID L2CAP(0x0100) */

0x35, 0x05,                 /* DataElSeq 5 bytes */

0x19, 0x00, 0x03,           /* UUID RFCOMM(0x0003) */

0x08, SPP_DEFAULT_CHANNEL,  /* uint8 Suggested RFCOMM
channel for SPP */

0x09, 0x00, 0x09,           /* BluetoothProfileDescriptorList(0x0009) */

0x35, 0x06,                 /* DataElSeq 3 bytes */

0x19, 0x11, 0x01,           /* UUID SerialPort(0x1101) */

0x09, 0x01, 0x02,           /* SerialPort Version (0x0102) */

0x09, 0x01, 0x00,           /* ServiceName(0x0100) = "SPP Dev" */

0x25, 0x07,                 /* String length 7 */

'S','P','P',' ','D', 'e', 'v'

};

在上面的SDP
Service Record中,ServiceClassIDList属性ID对应的属性值为:SerialPort (0x1101),这就是SPP服务对应的SDP标识符。客户端通过查找该标识符,来获取服务端是否支持SPP服务。其中ServiceClassIDList,ProtocolDescriptorList,L2CAP,RFCOMM,ServiceName是通用服务类属性,SerialPort Version是SPP服务特定的服务属性(私有属性)。某个服务的特定(私有)属性如何查找???。

通常属性ID和属性值封装在不同的数据单元(Data Element)里面,因此属性ID和属性值之间需要插入DataElSeq数据单元,用来记录属性值所占据字节数,这样服务器在解析SDP数据记录时,能够有效定位该属性记录的边界。

上述的SDP记录用jeason表示为:

ServiceClassIDList(0x0001){

SerialPort(0x1101);

}

ProtocolDescriptorList(0x0004){

L2CAP(0x0100){

RFCOMM(0x0003){

RFCOMM_DEFAULT_CHAN;

}

}

}

BluetoothProfileDescriptorList(0x0009){

SerialPort(0x1101);

}

SerialPortVersion;

ServiceName(0x0100){

SERVICENAME_STR;

}

1.1.5   
服务查找

服务查找允许Client基于包含服务记录的属性值,来获取特定服务记录的服务记录句柄(Service Record Handle)。 当一个SDP Client有某个服务记录句柄时,它可以请求特定的属性值。SDP不提供基于任意属性值的服务记录查找,只提供基于UUID的查找 。

5.1 UUID

UUID是一个128位的值,蓝牙Base
UUID值为0x00000000-0000-1000-8000-00805F9B34FB ,其他已定义的UUID可参考<UUID>。为了简化实用,我们实用16-bit和32bit UUID来代表真实的UUID。

5.2 服务搜索模式(Service Search
Patterns)

服务搜索模式使用UUID列表来定位匹配的服务记录。

1.1.6   
服务浏览

SDP提供了基于服务类共享属性机制来浏览服务,这个属性被称为BrowseGroupList,Client通过创建一个包含代表根浏览组的UUID的服务搜索模式来浏览Server的服务。

1.1.7   
数据表示(物理存储形式)

SDP的使用数据单元(Data
Element)来表示数据(属性ID,属性ID范围,属性值),数据单元是一种类型化的数据表示,它由两个字段组成:首部字段(Header Field)和数据字段(Data Field)。

首部字段包含两个部分: 类型描述符(Type
Descriptor)和大小描述符(Size Descriptor) 。

数据字段是一个字节序列,其长度由大小描述符指定,其含义则由类型描述符指定。

7.2类型描述符

数据单元的类型使用5-bit的类型描述符来表示,它包含在首部字段第一个字节的高五位。下面是已经定义的类型:

7.2 大小描述符

数据单元的大小描述符包含在首部字段第一个字节的低三位 ,它表示为的大小指数,其后为0/8/16/32bits ,大小指数的编码如下:

7.3 数据单元实例

1.1.8   
协议说明

SDP使用Request/Response模型 ,其中每个事务(Transaction)包含一个请求协议数据单元(PDU)和一个响应PDU,SDP使用L2CAP作为传输协议,在建立连接并发出SDP Request后 在给定的时间内,只有收到该Request的Response后,才能发出其他的Request,传输采用Big-Endian,高位先低位后的方式。

8.1 PDU格式

SDP PDU包含一个Header和Parameters,Header包含三个字段: PDU ID, Transaction ID, ParameterLength。

其中,Header三个字段的含义分别如下:

8.2 Partial Responses And Continuation
State

8.3 错误处理

当一个Server认为Client的Request格式不正确或其他原因导致没有合适的Response时 ,应该回应一个SDP_ErrorResponse
PDU(PDU ID=0x01),同时,其Parameters为ErrorCode,ErrorCode详细信息如下:

8.4 服务查找事务

ServiceSearch Transaction

8.4.1  SDP_ServiceSearchRequest PDU

SDP_ServiceSearchRequest PDU(PDU ID=0x02)的Parameters包括:

ServiceSearchPattern,  /*目标服务(UUID标识)列表*/

MaximumServiceRecordCount,  /*搜寻最大最大返回服务记录数*/

ContinuationState      /*搜索附加的额外参数*/

ServiceSearchPattern(Size:
Varies):

Value

Parametr
Description

Data
Element Sequence

ServiceSearchPattern是一个数据单元序列,每个单元是一个UUID,单元数为1~12

MaximumServiceRecordCount(Size:
2 Bytes):

Value

Parametr
Description

N

MaximumServiceRecordCount是一个16-bit数,指定可返回的了最大的服务记录句柄,取值范围: 0x0001~0xFFFF

ContinuationState(Size:
1~17 Bytes):

Value

Parametr
Description

Continuation
State

ContinuationState是一个8-bit数N,随后的N Bytes是Continuation State信息,N的范围为0~16,0表示没有Continuation State

8.4.2  SDP_ServiceSearchResponse PDU

SDP_ServiceSearchResponse PDU(PDU ID=0x03)的Parameters包括:

TotalServiceRecordCount,     /*搜寻到的服务记录总条目数*/

CurrentServiceRecordCount,  /*本次搜寻返回的服务记录条目数*/

ServiceRecordHandleList,     /*搜寻到的服务记录句柄列表*/

ContinuationState           
/*搜寻返回的额外附属信息*/

8.5 服务属性事务

ServiceAttribute
Transaction

8.6 服务属性查找事务

ServiceSearchAttribute
Transaction

TIP: 8.4.2, 8.58.6均为详细定义,此处不累述,详情见规范

1.1.9   
服务属性定义

9.1 Universal Attribute Definition

9.2 ServiceDiscoveryServer Service Class
Attribute Definitions

9.3 BrowseGroupDescriptor Service Class
Attribute Definitions

TIP: 9主要描述了属性ID,属性值类型及属性相关说明,详情见规范

上述介绍全部来自:http://www.cnblogs.com/hzl6255/p/3826558.html

关于SDP,更多内容,可参考如下文章 :

<蓝牙的SDP协议总结> http://blog.sina.com.cn/s/blog_69b5d2a50101egbb.html

<SDP协议译稿> http://www.cnblogs.com/strive-forever/archive/2011/11/04/2236640.html

<FTS抓包看蓝牙的SDP整个过程> http://blog.sina.com.cn/s/blog_69b5d2a50101f23c.html

1.2      
ADK实现

由于SDP数据记录的维护都封装在BlueCore内,开放给开发人员的东西并不多,因此SDP的实现部分也比较简单。SDP的实现主要涉及到三个库:connect库,SDP parse库,service库,它们之间的关系图如下:

其中SDP Parse库和service库是一些帮助函数,用于帮助解析SDP请求返回的服务数据。重点应该放在Connect库。根据设备所处的角色不同,Connect库分为两大类,服务器端API和客户端API,(当然服务器本身也可以调用查询API获取自身的服务,但是那样使用的场合很少)。

客户端在开始SDP搜索之前,通常需要建立SDP会话(session),这一步骤通常在inquiry阶段完成,因此inquiry阶段完成后,客户端缓存了服务器端部分支持的服务列表(hsp,hfp,a2dp,avrcp)。在后续的通信过程中,如果需要获取服务器是否支持其它某项服务,只需要继续发送下面三个接口即可:

ConnectionSdpServiceSearchRequest();

ConnectionSdpAttributeSearchRequest();

ConnectionSdpServiceSearchAttributeRequest();

在inquiry阶段,如何进行SDP搜索,以及如何保存搜索结果,即后续如何利用这些结果,后面再继续探寻。

SDP模块通信机制与L2CAP,RFCOMM基本类似,这里不再赘述。

九、SDP的更多相关文章

  1. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  2. 谈谈一些有趣的CSS题目(九)-- 巧妙的实现 CSS 斜线

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  3. CRL快速开发框架系列教程九(导入/导出数据)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  4. Python(九)Tornado web 框架

    一.简介 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过 ...

  5. 我的MYSQL学习心得(九) 索引

    我的MYSQL学习心得(九) 索引 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  6. Atitit各种SDM 软件开发过程SDP sdm的ddd tdd bdd设计

    Atitit各种SDM 软件开发过程SDP sdm的ddd tdd bdd设计 1.1. software development methodology (also known as SDM 1 1 ...

  7. 【Oracle 集群】Linux下Oracle RAC集群搭建之基本测试与使用(九)

    Oracle 11G RAC数据库安装(九) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总 ...

  8. Jsp的九大对象,七大动作,三大指令

    jsp九大内置对象:1>out 向客户端输出数据,字节流.如out.print(" dgaweyr"); 2>request 接收客户端的http请求.String g ...

  9. 今天我们来认识一下JSP的九大内置对象

    虽然现在基本上我们都是使用SpringMVC+AJAX进行开发了Java Web了,但是还是很有必要了解一下JSP的九大内置对象的.像request.response.session这些对象,即便使用 ...

随机推荐

  1. Java学习:Annotation注解

    Annotation不算常用的技术,早前用它写了一些玩意儿,过了一年又忘干净了,今天写点东西记下来,以备再忘之需. java.lang.annotation,接口 Annotation.对于Annot ...

  2. Alpha阶段冲刺项目总结(补充)

    Alpha阶段冲刺阶段总结(补充) 此篇博客为"作业七:Alpha版本冲刺阶段" 与 "作业八:Alpha阶段项目总结" 的总结版. 一.项目预期计划vs实际进 ...

  3. js模版引擎handlebars.js实用教程——循环中使用索引

    <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content="text/ ...

  4. Android移动APP开发笔记——Cordova(PhoneGap)通过CordovaPlugin插件调用 Activity 实例

    引言 Cordova(PhoneGap)采用的是HTML5+JavaScript混合模式来开发移动手机APP,因此当页面需要获取手机内部某些信息时(例如:联系人信息,坐标定位,短信等),程序就需要调用 ...

  5. 一则JVM memory leak解决的过程

    起因是我们的集群应用(3台机器)新版本测试过程中,一般的JVM内存占用 都在1G左右, 但在运行了一段时间后,慢慢升到了4G, 这是一个明显不正常的现象. 定位 过程: 1.先在该机器上按照步骤尝试重 ...

  6. atitit 短信接口规范与短信解决方案.docx

    atitit 短信接口规范与短信解决方案.docx 1.1. 国内比较著名的短信提供商1 1.2. 短信接口规范1 1.3. 短信sdk构成1 1.4. 短信的实现1 1.5. SmsServiceY ...

  7. Atitit java 二维码识别 图片识别

    Atitit java 二维码识别 图片识别 1.1. 解码11.2. 首先,我们先说一下二维码一共有40个尺寸.官方叫版本Version.11.3. 二维码的样例:21.4. 定位图案21.5. 数 ...

  8. Jsp练习——连接数据库模拟登录

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  9. salesforce 零基础开发入门学习(四)多表关联下的SOQL以及表字段Data type详解

    建立好的数据表在数据库中查看有很多方式,本人目前采用以下两种方式查看数据表. 1.采用schema Builder查看表结构以及多表之间的关联关系,可以登录后点击setup在左侧搜索框输入schema ...

  10. ngResource提交json数据如何带参数

    ngResource提交json数据如何带参数 直接使用ngResource和REST服务接口交互可以让程序显得简洁,前提是配置好跨域和OPTIONS请求的支持,与此同时,如果需要带些额外的参数,有两 ...