SIP协议学习(1)

1 SIP协议架构

名称详细
Transaction User事务用户
Transaction Layer事务层
Transport Layer传输层
Syntax and Encoding语法和编码层

当一个事务用户发出一个请求,它首先创建一个客户事务实例,并且将目的IP地址、端口和“请求”消息一起发送。

2 SIP编码

SIP协议是一个基于文本的协议,使用UTF-8字符集,一个SIP消息格式大致如下:

一般消息	 = 起始行
		  *消息包头
		  CRLF
		  [消息正文]

起始行 = 请求行 / 状态行
起始行、每一个“消息包头”行、空行,都必须由回车换行组成。

请求

SIP请求的特征是在起始行包含一个请求行,请求行包含的内容如下:

请求行 = Method(空格)Request-URI(空格)SIP版本(CRLF)

其中,

  • Method:本协议规定了6中方法,REGISTRER、INVITE、ACK、CACEL、BYE、OPTION。
  • Request -URI:Request-URI是一个SIP URI,标志了这个请求所用到的用户或者服务地址,禁止包含空白字符或者控制字符,并且禁止用“<>”括上。除了支持以上,还支持tel-URI模式。
  • SIP版本:请求和应答消息都包含当前使用的SIP版本,一般包含SIP/2.0,作为版本号,对大小写虽然不敏感,但是在实现中必须发送大写。

响应

SIP响应的特征是在起始行包含一个状态行,状态行包含的内容如下:

状态行 = SIP版本(空格)Status-Code(空格)Reason-Phrase

其中,

  • Status-Code是一个3位数的结果码,用来表示处理请求的结果,第一个数字表示应答的类型,接下来的两个数字并不做分类使用。
类 别描述动作
1xx信息用来只是呼叫完成前的状态,也被称为临时响应。
2xx成功请求处理成功。如果是INVITE消息的,应回应ACK消息;否则表示停止重发请求。
3xx重定向服务器返回可用的位置。客户端应该重试请求到另一个服务器上。
4xx客户端错误请求失败,由于客户端的错误。客户端可以根据响应修改请求并重试。
5xx服务器故障请求失败,由于服务器的错误。请求可以向另一台服务器重试。
6xx全局失败请求失败。是全局性错误,该请求不应该向其他服务器再次尝试。
  • Reason-Phrase是对状态码的自然语言翻译,是用来给用户看的,客户端并不要求一定要显示或者解释这个字段。

头域

头域的格式如下:

header = header-name HCOLON header-value *(COMMA header-value)

其中:HCOLON表示冒号的意思 :
COMMA表示逗号的意思

一个头域可以有多个域值,它们之间要用逗号隔开。头域与头域之间没有固定的顺序,但是为了代理服务器解析方便,建议把路由相关的头域放在前面。值得注意的是,多个同名头域之间是有顺序要求的,如果顺序不同代表着不是同一个消息。

每个头域值都是依赖于它的头域名,域值格式为:
field-name: field-value *(;parameter-name=parameter-value)

虽然在域值中可以有多个parameter-name=parameter-value对,但是parameter-name是不允许重复的。sip协议头域不区分大小写,但是引号串的字符串是大小写敏感的。

比如,如下是合法且等效的
Route: <sip:alice@atlanta.com> 
Subject: Lunch 
Route: <sip:bob@biloxi.com> 
Route: <sip:carol@chicago.com> 
Route: <sip:alice@atlanta.com>, <sip:bob@biloxi.com> 
Route: <sip:carol@chicago.com> 
Subject: Lunch 
Subject: Lunch 
Route: <sip:alice@atlanta.com>, <sip:bob@biloxi.com>, 
<sip:carol@chicago.com>

再比如,如下是parameter的格式

SIP/2.0 200 OK 
Via: SIP/2.0/UDP server10.biloxi.com 
;branch=z9hG4bKnashds8;received=192.0.2.3 //;parameter-name=value
Via: SIP/2.0/UDP bigbox3.site3.atlanta.com 
;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2 

消息正文

如果携带消息体正文,需要在头域中使用Content-Type明确指示携带的内容类型,如果存在编码,还需要在头域中使用content-Encoding明确指示携带的编码类型。另外,需要在头域中使用Content-Length指示消息体长度。

3 用户代理客户端行为

产生请求

一个合法的SIP请求必须至少包含如下头域:TO,FROM,Cseq, Max-Forwards, Via这些字段,这6个字段是SIP消息的基本组成部分,它们提供了用于路由的核心信息。

例如,一个INVITE消息格式如下:
INVITE sip:bob@biloxi.com SIP/2.0 
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds 
Max-Forwards: 70 
To: Bob <sip:bob@biloxi.com> 
From: Alice <sip:alice@atlanta.com>;tag=1928301774 
Call-ID: a84b4c76e66710@pc33.atlanta.com 
CSeq: 314159 INVITE 
Contact: <sip:alice@pc33.atlanta.com> 
Content-Type: application/sdp 
Content-Length: 142
- Request-URI

初始的Request-URI必须设置为“TO”头域的值(REGISTER方法中有点特殊,后文讲),该字段可能会被预先设置的路由表影响。

- To

该头域指定请求的“逻辑”接收地,这个域内的地址不一定是请求的最终接收者,可以用SIP\SIPS URI以及tel-URI,To头域允许有一个显示用的姓名。

一般用户输入的字符串加上“@”命令标志和主机名字组合成为SIP,比如sip: bob@example.com。以下就是一个头域的例子:
To: Carol sip:carol@chicago.com

- From

From头域包含了请求发起者的逻辑标志,包含一个URI并且可以包含一个显示的姓名。SIP可以用这个头域来实现对请求的检查和选择一个规则进行对请求的处理(比如自动呼叫拒绝,凡是某人发过来的东西一律无视)。
From头域必须包含一个由UAC产生的新的tag参数。

例如:
From: "Bob" <sips:bob@biloxi.com> ;tag=a48s
From: sip:+12125551212@phone2net.com;tag=887s
From: Anonymous <sip:c8oqz84zk7z@privacy.org>;tag=hyh8
- Call-ID

Call-ID是一系列消息中,区分一组消息的唯一标识,在对话中的任一UA的所有请求和应答的Call-ID必须一致,在UA的每次注册中,都应该是一样的。全局唯一性要由UAC保证,建议使用密码乱序随机串(RFC 1750)产生Call-ID,在实现中,可以用localId@host的格式产生,该字段是大小写敏感的,需要通过简单的逐个字节比对的方法比较。

例如:
Call-ID: f81d4fae-7dec-11d0-a765-00a0c91e6bf6@foo.bar.com
- CSeq

该头域是用来区分不同事务并且作为事务的顺序使用的,由一个Method和一个顺序号码组成。对于dialog外的非REGISTER请求来说,顺序号码是任意的,这个顺序号码必须由32位的无符号整数表达,必须小于2^31,。

例如:
CSeq: 4711 INVITE
- Max-Forwards

该头域用来限制请求到目的地中间的跳转,它包含一个每隔一个跳转就自动减一的数字,如果该字段到达目的地址之前就减到0,会报告一个483错误回应。该字段的缺省值是70。

- Via

该字段标志了用于事务传输的传输设备,并且也标志了应答送回的地址,只有在选择将用于下一跳的传输后,才添加Via头域字段。
UAC创建一个请求,必须在头域中添加一个Via域,protocol名字和版本必须分别是SIP和2.0,Via头域必须包含一个branch参数,这个参数用于区分请求创建的事务,这个参数客户端和服务器都会使用。利用branch ID参数的唯一性来作为transaction ID。

本标准产生的branch
ID必须用“z9h64bk”开头,这七个字母是一个乱数cookie,这样服务器收到请求之后,可以很方便的知道这个branch ID是否由本规范所产生。

- Contact

在任何会建立一个对话的请求中,Contact头域必须提供和包含一个SIP或者SIPS URI,只有INVITE请求会建立一个会话,contact的作用域是全局性的,头域中包含的URI是UA能够接收请求的,这个URI必须是有效的,甚至在对话外的请求中的头域的URI也必须是有效的。

取消请求

CANCEL请求,就是用来取消客户端发起的上一个请求,特别的,它请求UAS终止上一个请求且对上一个请求产生一个错误的应答。CANCEL对UAS已经停止处理该请求并对该请求生成一个终结响应,如果UAS已经给出了终结应答,CANCEL是无效的,所以CANCEL请求的最大用处是取消需要服务器长时间处理的请求

比如INVITE请求发出后,发送CANCEL取消请求,在这个场景下,UAS接收到一个INVITE请求的CANCEL请求,当这个INVITE还没有得到终结应答前,UAS会停止振铃,并且给INVITE请求一个错误的应答(487,Request
Terminated)。

CANCEL请求不应该取消除了INVTIE之外的请求,因为除了该请求,其它的请求都是立刻响应的,创建一个CANCEL请求需要如下方式:

  1. 在CANCEL请求中的Request-URI,Call-ID,To,Cseq的数字部分,From头域都必须和被取消的请求头域一样,包含这些头域的tags,客户端创建的CANCEL必须只有一个via头域值,这个头域值和被取消的请求的最上一个Via头域值相同。Cseq请求头域的Method部分必须要CANCEL方法。如果被取消的请求包含一个Route头域,CANCEL请求也必须包含这个route头域值。
  2. 一旦CANCEL请求被创建,UAC应该检查是否收到原始请求的任何应答(临时的或者终结应答)。如果没有收到临时应该,这个CANCEL请求不能发送,直到UAC等到了第一个临时应答,如果原始请求已经收到一个终结应答,这个CANCEL也不应当发送,因为即使发送也没有任何作用。

4 下期预告

下一次讲一下注册吧

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值