以前写了一篇 bluedroid对于sdp的实现的源码分析 ,他其实对于sdp 协议自己的分析并很少,而是侧重于 sdp 处于Android bluedroid 架构中的代码流程,这篇文章,是针对SDP 的规范来整理SDP 协议自己的一些要点。html
概要:
咱们想想,两个陌生的设备(以前未有过交互)如何去发现对方支持什么服务呢?很容易想到,咱们须要一种协议,这种协议规定了服务在服务器上面是如何存储的以及对方如何可以经过这个协议来获取到数据,以及双方共同遵照的一些规定等等。编程
SDP全称是Service Discovery Protocol,它是一种服务发现的协议,它能够达成咱们上面提出的问题。这部分参考core_spec,Vol3-PartB。服务器
这样的一个协议应该具体实现一些什么?架构
那确定是会规定特定的数据格式,以及交互的流程。ide
下面就分以下的几部分来介绍SDP:oop
- 基本概念。
- 数据格式
- 交互流程
- 实例
基本概念:
Service Record:服务就是能够提供特定信息或者进行特定的行为,或者是能进行控制某些资源的一个实体。它的实现能够基于软件或者硬件,也能够是二者兼有。在服务器上面维护的关于一个servcie的全部信息的集合就是一个service record。它的全部信息每每都是用service attributes来表示的。源码分析

service attribute:它是对于service 各类属性的一种描述。好比service ID,service的name。一些常见的属性以下:spa


从上面的图中发现service attribute 由 attribute ID和attribute Value组成的。htm
Attribute ID:它是一个16位的无符号整数,它用来区分在同一个Service Record之中的不一样attribute,同时它也每每暗含与它相关的 Attribute Value的语义。注意它的用data element 来表示的。对象
Attribute Value:它是一串不定长的数据,它的含义是由与它对应的Attribute ID以及它所在的service类别来决定的。注意它的数据格式的是data element。(后续介绍)
Service class:它就是一种service的类别,它提供了全部属于这个类别的attributes的定义,它相似面向对象编程里面的类,具体的service是类的实例,一个具体的service 它可能隶属多个类别。相似面向对象的里面的继承。固然每一个class自己也是要和别的class来作以区分的,承担这项任务的变量叫service class identifier,在service里面总由一个attribute叫作ServiceClassIDList,这个service class identifier就存储在这个attribute的attribute value 里面,这个值是一个UUID。
UUID:A UUID is a universally unique identifier that is guaranteed to be unique across all space and all time。注意它具备全局的惟一性。 它是128bit的值。
Service Search Patterns:这个是一串UUID,是用来搜索用的。
Data element:它由header和data两部分组成。其中,header部分又由两部分组成:类型描述符和大小描述符,前者是来描述data的类别,后者是来描述data 的大小。此概念很是重要。类型描述符是用header部分的高5bits来表示的。大小描述符是用header部分的低3个字节来描述的。下面看看这两个描述符具体的类别以及大小:


下面举个例子来讲明:

接下来 咱们看看:
数据格式:
数据的格式以下图:

PDU ID 表示这个PDU是做用,是用以区别其余的PDU
TransactionID:用以区别其余的Transaction
另外还有一个概念Continuation State:当SDP 服务器返回client 结果的时候,若是数据太大,那么就会分包,下面额度变量就是分包的标志,若是部分包,其值为0

接下来 ,咱们看看交互的基本的流程:
交互流程:
根据PUD id 的不一样,交互的流程也不一样,可是思路都是同样,都是CS的架构。

由于基本上面全部的交互流程都是同样的,下面只讲其中一个交互的流程。

下面来解析一下它的参数:
ServiceSearchPattern:这个匹配模式是由一串UUID组成的,一次最多包含12个UUID,UUID的表现形式是data element
MaximumAttributeByteCount:从response中返回的最大的PDU
AttributeIDList:这个参数包含的是一串attribute ID或者是attribute ID的范围,也能够是二者的组合。
ContinuationState: 这个参数的第一个字节表明长度,而后后面跟该长度个字节。这个state 是从reponse中返回的。而后再一次请求的时候放在参数里面。如何没有剩余的字节须要读取,那么设置为0
下面是对应的response 的PDU:

相应的参数解释以下:
AttributeListsByteCount:这里是count就是AttributeLists这里的字节数。
AttributeLists:这里的元素都是data element sequence,它是由attribute IDs和attribute values 来组成的pair
这里先结合btsnoop来分析一下,具体的SDP 流程是怎么样的?
相应的log:btsnoop_a2dp.cfa

从上面的log 能够看出,其PDU ID: SDP_ServiceSearchAttributeRequest ,这个命令是要先根据patterns来搜索特定的service,而后在搜索到service里面进行attribute的搜索。那么咱们看看这条命名对应的具体参数。

咱们应该还记得 pattern是第一个参数,其中包含的UUID是L2cap,那意味着只要包含L2cap的service都会match这个pattern,接下来的参数是说最多返回656 个字节。接下来的参数AttributeLists上面讲过,既能够是UUID,也能够是UUID的范围。这里参数是0x00 --0xFF
也就是说 返回match pattern的service的全部的attribute。
SDP里面是有专门的PDU来作browsing的,这里不做介绍。从上面的描述能够看出,虽然它没有作browsing,可是也至关因而browsing。
接下来,咱们看看对应这个request的response:

咱们按照数据格式,来分析一下,若是忘记了PDU的数据格式,能够回头看看上面写的。
07:PDU ID: SDP_ServiceSearchAttributeResponse
00 00 :Transaction ID: 0x0000
00 2b:Parameter Length: 43
根据 数据包格式,咱们知道接下来是Parameters了,咱们再次把这个parameter相关的PDU 放在这里:

00 26:Attribute List Byte Count: 38 表明这一包数据的AttributeLists 的byte的数量。
接下来就是AttributeLists的表达方式:

从上面的图能够知道其是Data Element Sequence
接着分析:
0x36 0x01 0xd7 = 0b00110 0b110 0x01 0xd7
其中0b00110 说明Type是 Data element sequence
0b110 说明参数的长度部分是由16个bits来表示的,也就是后面的0x01 0xd7,这个长度表明全部的返回的参数的长度,(后续的包是分包返回)并非这个包的长度。这里还须要注意一点的是这里的type是Data element sequence ,意味着接下来parameter部分都是Data element的格式。
接着分析:
接下来确定仍是data element的header部分
36 00 3b :0b00110 0b110 0x00 0x3b 说明接下来的 AttributeList 里面的数据元素仍是Data Element,而且 这个AttributeList的长度是的0x003b ,
接下来的数据是 :
09 00 00 = 0b00001 0b001 00 00 对应上面的data element说明Attribute ID的Type是Unsigned Integer,(注意根据上面的格式,第一个element是Attribute ID,接着是Attribute value),Attribute ID的SizeIndex是2 bytes,Attribute ID = 0x00 0x00
下面看下一个element 这个element 是对应上面的Attribute ID的Attribute value:
0a 00 01 00 00 = 0b00001 0b010 说明这个data element的Type是Unsigned Integer,用4个字节来表示 也即00 01 00 00

接下来的就是 下一个 attribute 了,其格式都是相似,只是表明的attribute不一样。在此再也不赘述。
最后再举个profile的例子,看看profile中是如何定义它的service的:
这里看A2dp 中关于其自身service的描述:这里只描述sink的状况:


从上面的service class ID 看出它是一个audio sink的service,涉及到protocol 有L2cap和AVDTP,与其相对应的profile 是A2dp
Supported Features是它有可能支持的feature,接下来还有provider name和Service name的描述。
下面看一下log实际的 搜索的状况,和上面的规范是一致:

end