Java, C# 和 VB 开发人员的 SDP 入门






4.78/5 (8投票s)
本文档旨在为希望快速了解协议工作原理和细节的 Java、C# 和 VB 程序员提供关于会话描述协议 (Session Description Protocol) 的技术概述。
会话描述协议 (SDP)
随着用于协商和定义通信会话参数的协议(例如会话发起协议)的出现,需要解释其目的和注册过程。会话描述协议 (SDP),在 RFC4566 中定义,通过提供会话特征和媒体定义的格式来实现这一点。作为会话协商的一部分,各方应就描述值、时序、各自的能力和所需的媒体格式达成一致。这种交换被称为“提问/应答模型”(Offer/Answer Model),并在 RFC3264 中正式化。SDP 可与多种传输协议一起使用,例如会话公告协议 (SAP)、会话发起协议 (SIP)、超文本传输协议 (HTTP) 等。
目录
SDP 消息中必须包含几个重要信息
- 会话名称。
- 会话的活动时间。
- 组成会话的媒体。
- 会话的所有者/发起者。
- 如何接收媒体(地址、端口等)。
还可以提供其他可选信息
- 会议将使用的带宽。
- 会话的目的。
- 负责人的联系信息。
- 时区信息。
- 扩展 SDP 的会话属性。
该协议的编码主要是 UTF8(描述性字段可以有其他编码,如“charset”属性指定 - 稍后定义)。每个信息都包含在一个字段中。每个字段都通过回车/换行符序列 [CRLF] 分隔。每个字段的格式为
<type> = <value>
其中 <type> 是一个不区分大小写且唯一的单字符字段名,<value> 是结构化文本,其格式取决于 <type>。它们由一个无填充的“=”(等号)分隔。
消息结构
SDP 消息包含三个主要部分,分别详细说明会话、时序和媒体描述。每条消息可能包含多个时序和媒体描述。每个字段必须按所示顺序出现。
会话描述
表 4 对消息进行了细分,并更详细地描述了每个部分。
字段 | 类型 | 选项/必需 | 描述 |
---|---|---|---|
协议版本 | v | M | 当前协议版本。根据 RFC4566,始终为“0”。 |
Origin | o | M | 会话发起者的名称和会话标识符。 |
会话名称 | s | M | 文本形式的会话名称。 |
会话信息 | i | O | 关于会话的文本信息。 |
URI | u | O | 指向补充会话信息的指针。 |
电子邮件地址 | e | O | 负责人的电子邮件联系信息。 |
电话号码 | p | O | 负责人的电话联系信息。 |
连接数据 | c | C | 连接类型和地址。 |
带宽 | b | C | 提议的带宽限制。 |
时序描述在此处 | |||
时区 | z | O | 考虑夏令时信息。 |
加密密钥 | K | O | 用于交换密钥的简单机制。很少使用。 |
属性 | A | O | 一个或多个扩展协议的属性。 |
媒体描述在此处 |
注意:M - 必需;O - 可选;C - 条件(连接数据必须出现在会话或媒体描述中)。
时序描述
字段 | 类型 | 选项/必需 | 描述 |
---|---|---|---|
时序 | t | M | 开始和结束时间。 |
重复时间 | r | O | 指定任何会话重复的持续时间和间隔。 |
时间表示为网络协议时间 (RFC1305):自 1900 年以来的秒数;间隔可以用 NTP 时间或类型化时间表示:一个值和时间单位(天 ('d')、小时 ('h')、分钟 ('m') 和秒 ('s'))序列。
因此,2010 年 8 月 1 日上午 10 点开始的一个小时会议,并在同一时间点一周后重复一次,可以表示为
t=3487140000 3487143600
r=604800 3600 0
或使用类型化时间
t=3487140000 3487143600
r=7d 3600 0
媒体描述
字段 | 类型 | 选项/必需 | 描述 |
---|---|---|---|
媒体描述 | m | M | 媒体定义,包括媒体类型(例如,“audio”)、传输详细信息和格式。 |
会话信息 | 与上面相同 | ||
连接数据 | 与上面相同 | ||
带宽 | 与上面相同 | ||
加密密钥 | 与上面相同 | ||
属性 | 与上面相同 |
属性
SDP 使用属性来扩展核心协议。属性可以出现在会话或媒体部分,并相应地划分为“会话级”或“媒体级”。
属性有两种形式
- 属性形式:“a=<flag>”传达会话的属性。
-
值形式:“a=<attribute>:<value>”提供一个命名参数。
Attribute | 表单 | 描述 |
---|---|---|
类别 | cat:<category> | 用于过滤会话的点分隔的层级类别。 |
关键词 | keywds:<keywords> | 有助于识别会话。 |
RTP 有效载荷类型 | rtpmap:<payload type> <encoding name>/<clock rate> | 将 RTP 有效载荷映射到编码、格式和时钟速率。 |
仅接收 | recvonly | 工具应以仅接收模式启动。 |
发送/接收 | sendrecv | 工具可以以发送和接收模式启动。 |
类型 | type:<conference type> | 类型包括“broadcast”(广播)、“meeting”(会议)和“moderated”(受控)。 |
字符集 | charset:<character set> | 会话名称和信息字段中使用的字符集。 |
语言 | lang:<language tag> | 会话的默认语言。 |
示例
以下是一个关于“SDP 实现”的研讨会演示的示例会话描述,该演示可通过 RTP 以音频和视频形式在地址 100.101.102.103 上可用,端口分别为 49170 和 51372。这是一个小时的研讨会,将于 2010 年 8 月 1 日上午 10 点开始,联系人是 John Doe,电子邮件为 jdoe@arrhus.com。
注意:所有代码示例在语言上都是无关紧要的。对于那些有兴趣进一步探索 SDP 的人,我们提供了推荐的 Java、.NET 和 C++ API 列表。 并且所有代码都应该能与其中任何一个配合使用,只需少量注释(我碰巧在此案例中使用了 Konnetic 的 SIP C# API)。
注意:Alice 调用 Bob 是 SDP 的原型“Hello World”应用程序的等价物。
- 创建 SDP 消息或结构。对于 RFC4566,协议版本为“0”。
- 添加 Origin 字段,包含唯一的会话 ID、版本、发起者的姓名和地址——地址可以是 IP 地址或完全限定域名 (FQDN)。在此示例中,jdoe 是发起者。会话 ID 为 2890844526,版本为 89。会话是在机器 214.191.7.5 上创建的。
- 添加会话名称和信息,包括指向包含更多信息的网站的链接。
- 添加负责人的联系信息。这是 John Doe 的电子邮件,包含全名。
- 添加有关如何接收会话的连接信息。地址可以是 IP 地址或完全限定域名 (FQDN)。在此示例中,使用了到会话主机的 IP 连接。
- 添加时序。至少有一个时间字段,也可以有多个。一个好的 API 会允许您提供 NTP 时间或
DateTime
。时间的输出将始终是自 1900 年以来的秒数(分别为 3487140000 和 3487143600)。这些时间表示 2010 年 8 月 1 日上午 10 点开始的一个小时会议。 - 现在,我们可以为会话添加属性。此属性作用域为会话,并指示应用程序应以仅接收模式启动会话。
- 在此示例中,我们添加了两个媒体描述部分。第一个是音频,端口为 49170,使用最小控制的 RTP 配置文件,运行在 UDP 之上。最后一个零是 RTP/AVP 的额外参数信息。
- 第二个媒体描述是视频,端口为 51372,使用最小控制的 RTP 配置文件,运行在 UDP 之上。最后的 31 是 RTP/AVP 的额外参数信息。此属性作用域为媒体描述。任何演示都将以纵向显示。
SdpMessage sdp = new SdpMessage();
sdp.Origin.UserName = "jdoe"; sdp.Origin.SessionId = 2890844526; sdp.Origin.SessionVersion = 89; sdp.Origin.Address = new IPHost("214.191.7.5");
sdp.SessionName = "SDP Implementation";
sdp.SessionInformation = "A Seminar on the session description protocol";
sdp.Uri = new Uri("http://www.arrhussdp.com/documents/sdpseminar.html");
sdp.Emails.Add(new EmailHeaderField("jdoe@arrhus.com", "John Doe"));
sdp.Connection.Address = new IPHost("100.101.102.103");
TimeDescriptionHeaderField td = new TimeDescriptionHeaderField();
td.Timings.Start = new SdpTime(new DateTime(2010, 7, 1, 10, 0, 0, 0));
td.Timings.Stop = new SdpTime(new DateTime(2010, 7, 1, 11, 0, 0, 0));
sdp.TimeDescriptions.Add(td);
sdp.Attributes.Add(new AttributeHeaderField("recvonly"));
MediaHeaderField mh = new MediaHeaderField(SdpMedia.Audio,49172,
SdpMediaProtocol.RtpAvp,"0");
sdp.MediaDescriptions.Add(new MediaDescriptionHeaderField(mh));
MediaHeaderField mh1 = new MediaHeaderField(SdpMedia.Video, 51372,
SdpMediaProtocol.RtpAvp, "31");
MediaDescriptionHeaderField md = new MediaDescriptionHeaderField(mh1);
md.Attributes.Add(new AttributeHeaderField("orient", "portrait"));
sdp.MediaDescriptions.Add(md);
注意:两个媒体描述(以 m 开头的行)定义了音频和视频配置文件。这些配置文件在实时传输协议 (RTP) 规范 RFC3550 及其配套的最小控制 RTP 音视频会议配置文件 RFC3551 中有描述。
SDP 消息
最终的 SDP 消息应与以下内容完全一致
v=0
o=jdoe 2890844526 89 IN IP4 214.191.7.5
s=SDP Implementation
i=A Seminar on the session description protocol
u=http://www.arrhussdp.com/documents/sdpseminar.html
e=jdoe@arrhus.com (John Doe)
c=IN IP4 100.101.102.103
t=3487140000 3487143600
a=recvonly
m=audio 49170 RTP/AVP 0
m=video 51372 RTP/AVP 31
a=orient:portrait
SDP 库和 API
通常,SDP API 是在 SIP 库中实现的,因此此列表与推荐的 SIP 库相吻合。它并非详尽无遗;它们只是我遇到的最好的。一个好的 SDP API 的明智标准是它是否支持强类型字段、合理地实现了时序,并提供了许多有用的枚举。
语言 | 链接 | 描述 |
---|---|---|
Java | NIST 的 SIP 库 | 美国国家标准与技术研究院的参考 API。 |
C#, VB 等。 | Konnetic 的 SIP .NET 库 | 文档齐全的低级 SIP 和 SDP 栈。 |
C#, VB 等。 | Microsoft 的统一通信服务器 | 高级 SIP、SDP 和 RTP 栈。 |
C++ | PJSIP SIP 栈 | 轻量级但功能齐全且高度可移植的 SIP 栈。 |
测试工具
测试工具至关重要,因为任何与 SIP 应用程序和服务器交互的应用程序都必须遵守标准。
工具 | 描述 |
---|---|
SIPp | 惠普的 SIP 流量生成器。 |
PROTOS | 来自芬兰奥卢大学的测试应用程序。 |
ETSI TS 102 027-2 | SIP 测试呼叫流程列表。 |
延伸阅读
- M. Handley 等人,“SDP: 会话描述协议” RFC4566 2006。
- J. Rosenberg 等人,“SIP: 会话发起协议” RFC3261 2002。
- H. Schulzrinne。(2010) Henning Schulzrinne。[在线]。http://www.cs.columbia.edu/~hgs/
- A. B. Johnston, SIP: 理解会话发起协议,第三版。波士顿,马萨诸塞州,美国:Artech House,2007。
- H. Schulzrinne 等人,“RTP: 实时应用程序的传输协议” RFC3550 2003。