RFC3261(7 消息定义)

    SIP是一个基于文本的协议,使用UTF-8字符集(RFC2279[7])。

一个SIP消息既可以是一个从客户端到服务器端的请求,也可以是一个从服务器端到客户端的一个应答。

    请求(7.1)和应答(7.2)消息都基于RFC2822格式,只是在字符集上和语法细节上有所不同。(比如SIP允许头域不是标准的RFC2822头域)。这两种消息类型都由一个起始行,一个或者多个头域,一个标明头域结束的回车换行,一个可选的消息体组成。

 

一般消息=  起始行

*头域

CRLF

[消息体]

起始行= 请求行/状态行

 

    起始行、每一个头域字段行,空行都必须由回车换行组成(CRLF)。即使没有消息体,也必须有一个空行标明头域的结束。

    除了在字符集上的区别以外,很多SIP的消息和头域的格式都和HTTP/1.1一样。我们在这里就不重复它的语法和语义了,我们用[HX.Y]来标志HTTP/1.1规范(RFC2616[8])的X.Y节的描述。

    然后,SIP并非一个HTTP的扩展。

7.1 请求

    SIP请求是根据起始行中的请求行来区分的。一个请求行包含Method,Request-URI,和协议版本,彼此之间用SP(单个空格)分隔。

    请求行由CRLF(回车换行组合)结束。除了用作行结束标志以外,不允许CR或者LF出现在其他地方。在任何元素中,不允许出LWS(任意数量的空格)。

 

Request-Line = Method SP Request-URI SP SIP-VERSION CRLF

Method: 本规范规定了6中方法:REGISTER用于登记联系信息,INVITE,ACK,CANCEL用于建立会话,BYE用于结束会话,OPTIONS用于查询服务器所提供的能力。在按照RFC标准文档化的SIP扩展中可能包含其他的方法。

Request-URI: Request-URI是一个SIP或者SIPS URI,他们在19.1节由描述。也可以是一个通用的URI(RFC 2396[5])。它标明了请求所发往的用户或者服务的地址。Request-URI禁止包含空白字符或者控制字符,并且禁止用”<>”括上。

    SIP 元素可以支持除了SIP或者SIPS之外的其他方式的Request-URIs。比如”tel” URI方式(RFC 2806[9])。SIP元素可以用他们自己的机制来转换non-SIP URIs到SIP URI,SIPS URI或者其他什么格式的URI。

SIP-Version:请求和应答消息都包含当前使用的SIP版本,这个遵循[H3.1](类似HTTP用SIP替代,用SIP/2.0替代HTTP/1.1)中关于版本的规定,版本依赖,升级版本号。      一个应用发出的SIP消息一定要包含SIP-Version “SIP/2.0”。这个SIP版本串是大小写不敏感的,但是在实现中必须发送大写。

不像HTTP/1.1,SIP把版本号当作一个文本串处理。实际上,没有什么区别。

7.2应答

    SIP应答和SIP请求的区别在于以一个状态行作为它的起始行。状态行由协议版本、状态吗和状态描述组成,每一个元素之间用一个SP(空格)分隔。

    除了最后用作结束标志以外,CR/LF不允许出现在其他地方。

status-line = SIP-VERSION SP STATUS-CODE SP Reasong-Phrase CRLF

状态码 是一个3位数字的结果码,用来标志处理请求的结果。Reason-Phrase是一个简短的Status-Code描述。Status-Code是为了能自动处理使用的,但是Reason-Phrase是用来给用户看得。一个客户端并不要求一定要显示或者解释这个Reason-Phrase。

    本文档建议设置这个reason-phrase,实现时可以选择其他文本,比如用请求包头中指定的合适语言来显示。

    status-code的第一个数字表示了应答的类型。接下来两个数字并不作分类使用。因此,任何100到199的状态码可以统称位”1xx应答”,类似的,在200到299的可以统称位”2xx应答”,依此类推。SIP/2.0允许6类应答:

1xx:临时应答-请求已被接收,正在处理这个请求。

2xx:成功处理-请求已被成功接收、解析、受理。

3xx:重定向-为了处理该请求,需要进一步的操作

4xx:客户端错误--请求包含错误的语法或者不能被服务器处理。

5xx:服务器错误-服务器不能正确的处理这个显然合法的请求。

6xx:全局错误-请求不能被任何服务器处理。

21节定义了详细的状态码说明。

7.3 头域

    SIP头域和HTTP头域在语法和语义上都比较类似。尤其是,SIP头域遵循[H4.2]关于消息头的语法的定义,并且遵循多行的扩展头域的规则。然而后者在HTTP规范中支持隐式的空白和折叠。本规范遵循RFC2234[10],并且把明确的空白和封装作为内在的语法规则。

    [H4.2]也规定了具有相同域名的多个域可以合并到一个头域中,他们的值以逗号分隔列表显示,。这个也适用于SIP,但是因为语法不通,细节上略有不同。实际上,任何SIP的包头语法都是基于如下范式的:

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

对于拥有同样域名的头域,可以合并为一个头域,其值采用逗号分隔列表显示。Contact头域除了当域值是”*”之外,都允许采用逗号分割的列表方式。

7.3.1 头域格式。

    头域遵循在RFC2822的2.2节定义的通用头域格式。每一个头域都由一个域名加上冒号和域值组成。

field-name:field-value

    消息头的正式语法将在25节中详细介绍。

    在消息头中,允许在冒号的左右有任意个数的空白;但是,在实现时,建议避免域名和冒号中间有空格,并且建议在冒号和值之间使用单个空格(SP)。

Subject:         lunch

Subject    :     lunch

Subject         :lunch

Subject: lunch

    上面的都是合法的,也是相等的,但是推荐使用最后一种方式。

头域可以扩展为多行的,只要在每一个附加行前边用至少一个SP或者水平TAB(HT)打头就可以了。这种多行的头域在行结尾并且在下一行之前的空白SP(或者HT)将被认为是一个单个的SP字符。所以,下边的例子是相等的:

Subject: I know you’re there, pick up the phone and talk to me!

Subject: I know you’re there,

pick up the phone,

and talk to me!

    头域中的不同字段名的头字段的相关顺序并没有什么意义。但是,我们还是强烈建议与路由相关的域(VIA,ROUTE,Record-Route,Proxy-Require,Max-Forwards,Proxy-Authorization等等)放在消息头的最前边,这样可以提高处理的速度。相同字段名的头字段之间的顺序非常重要。只有当单个头域的域值是可以用逗号分割的列表的时候,才可以表达成为同一个字段名的多个头字段(也就是说,遵循7.3定义的语法)。这意味着必须可以将同一个域名的多个头域在不改变消息语义的前提下,改换表达成为一对”域名: 域值”;这个转换是通过顺序增加每一个域的域值,域值之间用逗号分割。这个规则有几个例外,就是WWW-Authenticate,Authorization,Proxy-Authenticate,和Proxy-Authorization头域,这些头域的的语法并不遵循7.3中定义的通用格式,所以,他们并不能合并成为单个头域行。

   在实现上,必须既能够处理多个头域行的情况,也必须能够处理用逗号分割的合并的单个头域行的情况。

   下边的几组头域是相等的:

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>

 

下边各组是合法的,但是并不相等。

Route: <sip:alice@atlanta.com>

Route: <sip:bob@biloxi.com>

Route: <sip:carol@chicago.com>

 

Route: <sip:bob@biloxi.com>

Route: <sip:alice@atlanta.com>

Route: <sip:carol@chicago.com>

 

Route: <sip:alice@atlanta.com>,<sip:carol@chicago.com>,<sip:bob@biloxi.com>

 

    每一个头域值的格式依赖于它的头域名。它可以是任意顺序的UTF8编码的字节字符,也可以是一个空格、符号、分隔符、引号括起来的字串的组合。很多头域都会附带一个通用的域值格式。这个域值格式是由封号分开的参数名和参数值的组合:

field-name: field-value *(;parameter-name=parameter-value)

    尽管域值里边可以有任意数量的parameter-name/parameter-value对,但是不能允许有相同的parameter-name存在(唯一性)。

    除了特别定义的头域之外,在比较域名的时候是大小写不敏感的。头域中的域名、域值、parameter name/parameter-value也是大小写不敏感的。符号始终是大小写不敏感的。除非有特别的指定,引号中的字符串是大小写敏感的。例如:

Contact: <sip:alice@atlanta.com>;expires=3600

CONTACT: <sip:alice@atlanta.com>; ExPiReS=3600

相同。

Content-Disposition: session;handling=optional

content-disposition: Session;HANDLING=OPTIONAL

相同。

下边的两个头域不相同:

Warning: 370 devnull “Choose a bigger pipe”

Warning: 370 devnull “CHOOSE A BIGGER PIPE”

7.3.2 头域分类。

   有一些头域是仅仅在请求(或者应答)中有效的。这些头域叫做请求头域或者应答头域。如果消息中的头域与这个消息的类型不匹配(比如在应答消息中出现的请求头域),这个头域必须被忽略。20节定义了每一个头域的分类。

7.3.3 缩写格式

    SIP提供了一个用缩写格式来表达通用头域名字的机制。这个有助于避免消息过大而导致通讯层无法传输(比如在UDP传输的时候超过了最大传输单元(MTU))。这个缩写格式在20节定义。缩写格式的消息头域名字可以在不改变消息语义的情况下替代较长的消息头域名字。在单个消息中,头域名字既可以用长的格式,也可以用缩写格式。在实现中,必须同时支持对长名字和缩写名字的处理。

7.4消息体

    请求信息,包括本规范以后扩展的新请求,都可以包含一个消息体。对消息正文的解释依赖于请求的方法(请求类型)。

    对于应答消息来说,请求方法和应答状态码决定了消息体的格式。所有的应答消息都可以有一个消息体。

7.4.1 消息体类型

    消息中的网络媒体类别必须在Content-Type头域中指明。如果消息体通过某种形式的编码,比如压缩等等,必须在Content-Encoding 头域中指明,否则Content-Encoding域必须忽略。若可以,消息体的字符集作为Content-type头域的值的一部分表达。

    在RFC2046[11]中定义的多部分”multipart” MIME类型可以在消息体中应用。在由多部分组成的消息体发送的时候,如果接收方的Accept域中不支持包含多部分的消息体,那么发送方必须发送一个非多部分的消息体。

   SIP消息可以包含二进制的消息体或者部分消息体。如果发送方没有显式的指定字符集参数,媒体的文本子类型会是缺省的字符集”UTF-8”。

7.4.2 消息体长度

    在Content-Length头域中存放了消息体的字节长度。第20.14节讲述了本域的详细解释。

    HTTP/1.1的“chunked”传输编码方式并不适用于SIP。(备注:chuncked编码传输方式是通过把消息体分为一系列的块来传输的,每一块有它自己的大小标记) 

7.5 分帧的SIP消息

    不同于HTTP的是,SIP实现可以使用UDP或者其他非可靠传输协议。每一帧包括一个请求或者应答。第18节讲述了非可靠传输的限制。

    在处理以面向流的通讯为基础的SIP消息的时候,必须忽略在开始行之前的CRLF[H4.1]。

    Content-Length头域用来确定每一个SIP消息在通讯流中的结束位置。在基于面向流通讯基础上的SIP消息一定要使用这个头域。

posted @ 2012-10-31 22:15  坐看风起云涌  阅读(487)  评论(0编辑  收藏  举报