SIP简介
SIP(Session Initiation Protocol,会话初始协议)是一个基于文本的应用层控制协议,用于创建、修改和释放一个或多个参与者的会话。SIP 是一种源于互联网的IP 语音会话控制协议,具有灵活、易于实现、便于扩展等特点。这些会话可以是Internet多媒体会议、IP电话或多媒体分发。会话的参与者可以通过组播(multicast)、网状单播(unicast)或两者的混合体进行通信。
SIP 的一个重要特点是它不定义要建立的会话的类型,而只定义应该如何管理会话。有了这种灵活性,也就意味着SIP可以用于众多应用和服务中,包括交互式游戏、音乐和视频点播以及语音、视频和 Web 会议。
SIP 独立于传输层。SIP 使用用户数据报协议(UDP) 以及传输控制协议(TCP),将独立于底层基础设施的用户灵活地连接起来。SIP 支持多设备功能调整和协商。如果服务或会话启动了视频和语音,则仍然可以将语音传输到不支持视频的设备,也可以使用其他设备功能,如单向视频流传输功能。
SIP 会话使用多达四个主要组件:SIP 用户代理、SIP 注册服务器、SIP 代理服务器和 SIP 重定向服务器。这些系统通过传输包括了 SDP 协议(用于定义消息的内容和特点)的消息来完成 SIP 会话。
- 用户代理
SIP 用户代理(UA) 是终端用户设备,如用于创建和管理 SIP 会话的移动电话、多媒体手持设备、PC、PDA 等。用户代理客户机发出消息。用户代理服务器对消息进行响应。 - 注册服务器
SIP 注册服务器是包含域中所有用户代理的位置的数据库。在 SIP 通信中,这些服务器会检索出对方的 IP 地址和其他相关信息,并将其发送到 SIP 代理服务器。 - 代理服务器
SIP 代理服务器接受 SIP UA 的会话请求并查询 SIP 注册服务器,获取收件方 UA 的地址信息。然后,它将会话邀请信息直接转发给收件方 UA(如果它位于同一域中)或代理服务器(如果 UA 位于另一域中)。 - 重定向服务器
SIP 重定向服务器允许 SIP 代理服务器将 SIP 会话邀请信息定向到外部域。SIP 重定向服务器可以与 SIP 注册服务器和 SIP 代理服务器同在一个硬件上。
SIP通过以下逻辑功能来完成通信:
- 用户定位功能:确定参与通信的终端用户位置。
- 用户通信能力协商功能:确定参与通信的媒体终端类型和具体参数。
- 用户是否参与交互功能:确定某个终端是否加入某个特定会话中。
- 建立呼叫和控制呼叫功能:包括向被叫“振铃”、确定主叫和被叫的呼叫参数、呼叫重定向、呼叫转移、终止呼叫等。
常用的SIP请求消息如下:
- INVITE:表示主叫用户发起会话请求,邀请其他用户加入一个会话。也可以用在呼叫建立后用于更新会话(此时该INVITE又称为Re-invite)。
- ACK:客户端向服务器端证实它已经收到了对INVITE请求的最终响应。
- PRACK:表示对1xx响应消息的确认请求消息。
- BYE:表示终止一个已经建立的呼叫。
- CANCEL:表示在收到对请求的最终响应之前取消该请求,对于已完成的请求则无影响。
- REGISTER:表示客户端向SIP服务器端注册列在To字段中的地址信息。
- OPTIONS:表示查询被叫的相关信息和功能。
常用的一些响应消息:
- 100试呼叫(Trying)
- 180振铃(Ringing)
- 181呼叫正在前转(Call is Being Forwarded)
- 200成功响应(OK)
- 302临时迁移(Moved Temporarily)
- 400错误请求(Bad Request)
- 401未授权(Unauthorized)
- 403禁止(Forbidden)
- 404用户不存在(Not Found)
- 408请求超时(Request Timeout)
- 480暂时无人接听(Temporarily Unavailable)
- 486线路忙(Busy Here)
- 504服务器超时(Server Time-out)
- 600全忙(Busy Everywhere)
SIP基本场景分析
会话初始协议(Session Initiation Protocol)是一种信令协议,用于初始、管理和终止网络中的语音和视频会话,具体地说就是用来生成、修改和终结一个或多个参与者之间的会话。SIP的业务模式是一个点对点协议,其中有两个要素——SIP用户代理和SIP网络服务器。用户代理是呼叫的终端系统元素,而SIP服务器是处理与多个呼叫相关联信令的网络设备。用户代理本身具有一客户机元素(用户代理客户机UAC)和一服务器元素(用户代理服务器UAS)。客户机元素初始呼叫而服务器元素应答呼叫。这允许点到点的呼叫通过客户机-服务器协议来完成。下图是SIP业务的网络结构和各个参与者的关系。
协议的其他特点还有它是一个文本协议,所以易于调测,结构灵活;而且它是一个中性的底层传输协议,可用TCP或UDP(推荐UDP);同时呼叫和媒体信息同时传送:媒体信息的传送由SDP传送。
SIP是互联网工程任务组(IETF)多媒体数据和控制体系结构的一个组成部分,因此它与IETF的许多其他协议都有联系,例如RTP(实时传输协议)和SDP协议。SIP与许多其它的协议协同工作,仅仅涉及通信会话的信令部分(control message)。SIP报文内容传送会话描述协议(SDP),SDP协议描述了会话所使用流媒体细节,如:使用哪个IP端口,采用哪种编解码器等等。SIP的一个典型用途是:SIP“会话”传输一些简单的经过封包的实时传输协议流。RTP本身才是语音或视频的载体。
注册流程
(1)用户首次试呼时,终端代理A 向代理服务器发送REGISTER 注册请求;
(2)代理服务器通过后端认证/计费中心获知用户信息不在数据库中,便向终端代理回送401Unauthorized 质询信息,其中包含安全认证所需的令牌;
(3)终端代理提示用户输入其标识和密码后,根据安全认证令牌将其加密后,再次用REGISTER 消息报告给代理服务器;
(4)代理服务器将REGISTER 消息中的用户信息解密,通过认证/计费中心验证其合法后,将该用户信息登记到数据库中,并向终端代理A 返回成功响应消息200 OK。
注销流程
(1)终端向代理服务器发送register消息注销,其头中expire字段设置为0。
(2)代理服务器在收到后送回200OK响应,并将数据库中的用户有关消息注销。
基本呼叫建立过程
(1)用户摘机发起一路呼叫,终端代理A向该区域的代理服务器发起Invite请求;
(2)代理服务器通过认证/计费中心确认用户认证已通过后,检查请求消息中的Via头域中是否已包含其地址。若已包含,说明发生环回,返回指示错误的应答;若没有问题,代理服务器在请求消息的Via头域插入自身地址,并向Invite消息的To域所指示的被叫终端代理B传送Invite请求。
(3)代理服务器向终端代理A发送呼叫处理中的应答信息:100Trying。
(4)终端代理B向代理服务器送呼叫处理中的应答信息:100Trying。
(5)终端代理B指示被叫用户振铃,用户振铃后向代理服务器发送180Ringing振铃信息。
(6)代理服务器向终端代理A转发被叫用户振铃信息。
(7)被叫用户摘机,终端代理B向代理服务器返回表示连接成功的应答(200OK)
(8)代理服务器向终端代理A转发该成功指示(200OK)
(9)终端代理A收到信息后,向代理服务器发ACK信息进行确认
(10)代理服务器将ACK确认消息转发给终端代理B。
(11)主被叫用户之间建立通信连接,开始通话。
正常呼叫释放过程
(1) 正常呼叫
(2) 用户通话结束后,被叫用户挂机,终端代理B向代理服务器发送Bye消息。
(3) 代理服务器转发Bye消息至终端代理A,同时向认证、计费中心发送用户通话的详细信息,请求计费。
(4) 主叫用户挂机后,终端代理A向代理服务器发送确认挂断响应信息200OK。
(5) 代理服务器转发响应信息200OK。
会话更改流程
(1)用户代理服务端和代理客户端正常通话。
(2)用户代理服务端向用户代理客户端发送Invite信息,带有新的SDP协商信息。
(3)用户处理客户端回复200OK,并将协商后的SDP信息带回。
(4)用户代理服务端发送ACK给用户代理客户端进行确认。
被叫忙呼叫释放
(1)用户摘机发起一路呼叫,终端代理A向该区域代理服务器发起Invite请求;
(2)代理服务器向被叫终端代理B传送Invite请求。
(3)代理服务器向终端代理A发送呼叫处理中的应答信息:100Trying。
(4)终端代理B向代理服务器送呼叫处理中的应答信息:100Trying。
(5)呼叫请求送到被叫终端代理B后,被叫忙,终端代理B向代理服务器送486被叫忙响应。
(6)代理服务器向终端代理A转发该响应消息。
(7)终端代理A向代理服务器回送ACK确认消息。
(8)代理服务器向终端代理B送ACK确认信息。
被叫无应答流程一
(1)用户摘机发起一路呼叫,终端代理A向该区域代理服务器发起Invite请求;
(2)代理服务器向被叫终端代理B传送Invite请求。
(3)代理服务器向终端代理A发送呼叫处理中的应答信息:100Trying。
(4)终端代理B向代理服务器送呼叫处理中的应答信息:100Trying。
(5)被叫用户振铃,终端代理B向代理服务器送180Ring响应。
(6)代理服务器向终端代理A转发该响应信息。
(7)被叫久振铃无应答,终端代理A判断超时后向代理服务器送Cancel消息放弃该呼叫。
(8)代理服务器收到Cancel消息后,向终端代理A回送200OK响应。
(9)代理服务器将Cancel消息转发给终端代理B。
(10)终端代理B向代理服务器回送200OK响应。
(11)终端代理B向代理服务器送487请求已撤销的响应信息。
(12)代理服务器收到后回送ACK确认。
(13)代理服务器向终端代理A送487请求已撤销消息。
(14)终端代理A向代理服务器回送ACK确认。
注:以上步骤中的(10)到(12)无严格顺序关系。
被叫无应答流程二
(1)用户摘机发起一路呼叫,终端代理A向该区域代理服务器发起Invite请求;
(2)代理服务器向被叫终端代理B传送Invite请求。
(3)代理服务器向终端代理A发送呼叫处理中的应答信息:100Trying。
(4)终端代理B向代理服务器送呼叫处理中的应答信息:100Trying。
(5)被叫用户振铃,终端代理B向代理服务器送180Ring响应。
(6)代理服务器向终端代理A转发该响应信息。
(7)被叫久振铃无应答,终端代理B判断超时后向代理服务器送408Requesttimeout消息放弃该呼叫。
(8)代理服务器收到408Requesttimeout消息后,转发该消息给终端代理A。
(9)代理服务器回送ACK确认给终端代理B。
(10)终端代理A向代理服务器回送ACK确认。
注:以上步骤中的(9)到(10)无严格顺序关系。
遇忙呼叫前转
(1)用户摘机发起一路呼叫,终端代理A向该区域代理服务器发起Invite请求;
(2)代理服务器向被叫终端代理B传送Invite请求。
(3)代理服务器向终端代理A发送呼叫处理中的应答信息:100Trying。
(4)终端代理B向代理服务器送呼叫处理中的应答信息:100Trying。
(5)终端代理B忙线中,B向代理服务器发送486Busy Here响应。
(6)代理服务器向终端代理B发送ACK确认消息。
(7)代理服务器对此呼叫进行前转,向代理服务器C发送Invite请求消息。
(8)代理终端C收到后指示用户振铃,同时向代理服务器发送180Ringing响应。
(9)代理服务器向A转发收到的180Ringing响应。
(10)被叫用户C摘机接听电话,终端代理C向代理服务器返回表示连接成功的应答(200OK)
(11)代理服务器向终端代理A转发该成功指示(200OK)
(12)终端代理A收到信息后,向代理服务器发ACK信息进行确认
(13)代理服务器将ACK确认消息转发给终端代理B。
建立通信连接,开始通话。
(14)主叫用户挂机,终端代理A向代理服务器发送Bye消息,请求挂机。
(15)代理服务器转发Bye消息至终端代理C,指示C挂机。
(16)终端代理C向代理服务器发送确认挂断响应信息200OK。
(17)代理服务器转发响应信息200OK至A。
无应答呼叫前转流程
(1)用户A摘机发起一路呼叫,终端代理A向该区域代理服务器发起Invite请求;
(2)代理服务器向被叫终端代理B传送Invite请求。
(3)代理服务器向终端代理A发送呼叫处理中的应答信息:100Trying。
(4)终端代理B向代理服务器送呼叫处理中的应答信息:100Trying。
(5)被叫用户振铃,终端代理B向代理服务器送180Ring响应。
(6)代理服务器向终端代理A转发该响应信息。
(7)被叫久振铃无应答,代理服务器判断超时后向代理终端B送Cancel消息放弃该呼叫。
(8)代理终端B收到Cancel消息后,向代理服务器回送200OK响应。
(9)终端代理B向代理服务器送487请求已撤销的响应信息。
(10)代理服务器向终端代理B回送200OK响应。
(11)代理服务器对此呼叫进行前转,向代理服务器C发送Invite请求消息。
(12)代理终端C收到后指示用户振铃,同时向代理服务器发送180Ringing响应。
(13)代理服务器向A转发收到的180Ringing响应。
(14)被叫用户C摘机接听电话,终端代理C向代理服务器返回表示连接成功的应答(200OK)
(15)代理服务器向终端代理A转发该成功指示(200OK)
(16)终端代理A收到信息后,向代理服务器发ACK信息进行确认
(17)代理服务器将ACK确认消息转发给终端代理C。
建立通信连接,开始通话。
(18)主叫用户挂机,终端代理A向代理服务器发送Bye消息,请求挂机。
(19)代理服务器转发Bye消息至终端代理C,指示C挂机。
(20)终端代理C向代理服务器发送确认挂断响应信息200OK。
(21)代理服务器转发响应信息200OK至A。
呼叫保持
(1)用户摘机发起一路呼叫,终端代理A向该区域的代理服务器发起Invite请求;
(2)代理服务器通过认证/计费中心确认用户认证已通过后,检查请求消息中的Via头域中是否已包含其地址。若已包含,说明发生环回,返回指示错误的应答;若没有问题,代理服务器在请求消息的Via头域插入自身地址,并向Invite消息的To域所指示的被叫终端代理B传送Invite请求。
(3)代理服务器向终端代理A发送呼叫处理中的应答信息:100Trying。
(4)终端代理B向代理服务器送呼叫处理中的应答信息:100Trying。
(5)终端代理B指示被叫用户振铃,用户振铃后向代理服务器发送180Ringing振铃信息。
(6)代理服务器向终端代理A转发被叫用户振铃信息。
(7)被叫用户摘机,终端代理B向代理服务器返回表示连接成功的应答(200OK)
(8)代理服务器向终端代理A转发该成功指示(200OK)
(9)终端代理A收到信息后,向代理服务器发ACK信息进行确认
(10)代理服务器将ACK确认消息转发给终端代理B。
(11)主被叫用户之间建立通信连接,开始通话。
(12)代理终端B向代理服务器发送Reinvite消息,SDP的c域等于0,0,0,0。
(13)代理服务器转发此信息给代理终端A。
(14)代理终端A收到Reinvite后回应200OK响应。表示接受会话更改,同事根据协商结果修改会话方式。
(15)代理服务器转发200OK给代理终端B。
(16)代理终端B收到消息后向代理服务器发送ACK消息进行确认。
(17)代理服务器将ACK确认消息转发到代理终端A。
呼叫等待
(1)AB正常通话。
(2)在AB通话的阶段,用户C向A发起呼叫,终端代理C发送Invite消息给代理服务器。
(3)代理服务器向终端C回送100Trying响应,表示呼叫已在处理中。
(4)代理服务器把Invite消息转发给A。
(5)用户A振铃,并且终端A向代理服务器发送180Ring响应。
(6)代理服务器向终端C转发该响应信息。
(7)用户A按下呼叫保持键,代理终端A向代理服务器发送Invite消息,请求与代理终端C呼叫保持。
(8)代理服务器转发此消息给终端代理B。
(9)代理服务器向终端A回送100Trying响应,表示呼叫已在处理中。
(10)终端B收到呼叫保持请求后,发送200OK给代理服务器,表示接受呼叫保持。
(11)代理服务器转发200OK响应给终端代理A。
(12)代理终端A收到消息后向代理服务器发送ACK消息进行确认。
(13)代理服务器将ACK确认消息转发到代理终端B。
(14)终端代理A发送200OK给代理服务器,表示接受C的呼叫。
(15)代理服务器转发200OK给终端代理C。
(16)终端代理C向代理服务器回送ACK确认。
(17)代理服务器向代理终端A转发收到的ACK确认。
A、C之间开始通话。
(18)用户A挂机,终端代理A向代理服务器发送Bye请求消息。
(19)代理服务器转发Bye消息给终端代理B。
(20)终端代理C发送200OK给代理服务器,表示接受请求。
(21)代理服务器转发200OK响应给终端代理A。
(22)终端代理C重新发送Invite请求给代理服务器,请求和终端代理B恢复通话。
(23)代理服务器向代理终端B转发收到的Invite请求。
SIP报文浅析
SIP消息消息分两类:请求消息 和 响应消息。
请求消息(Request):客户端为了激活特定操作而发给服务器的SIP消息,包括INVITE,ACK,OPTIONS,BYE,CANCEL和REGISTER消息。UAC到UAS。
响应消息(Response):服务器向客户端反馈对应请求的处理结果的SIP消息,包括1xx,2xx,3xx,4xx,5xx,6xx响应消息,UAS到UAC。
SIP消息由三个部分组成:标识消息类型和目的地址的起始行,携带消息参数的头部以及承载任意附加信息的消息体。消息体中传送的最重要的信息就是由SDP(Session Description Protocol)协议描述的媒体控制信息,供终端协商并建立媒体信道。
SIP消息格式:由一个起始行(Start-line)、一个或多个字段(header fields)组成的消息头、一个标志消息头结束的空行(CRLF)以及作为可选项的消息体(Message body)组成,其中描述的头称为实体头
起始行
起始行分请求行(Request-Line)和状态行(Status-Line)两种。
请求行(Request-Line)
请求消息的起始行,由请求消息类型,请求目的发送地址Request-URI,SIP协议的版本号,之间用空格隔开。
请求行: 由请求类型、请求目的地址和协议版本号构成。请求类型有:INVITE,ACK,OPTIONS,BYE,CANCEL和REGISTER。
请求行的6种Request Method:
INVITE:用于发起呼叫请求。INVITE消息包括消息头和数据区两部分。INVITE 消息头包含主、被呼叫的地址,呼叫主题和呼叫优先级等信息。数据区则是关于会话媒体的信息,可由会话描述协议SDP 来实现。
BYE:当一个用户决定中止会话时,可以使用BYE 来结束会话。
OPTIONS:用于询问被叫端的能力信息,但OPTIONS 本身并不能发起呼叫。
ACK:对已收到的消息进行确认应答。
REGISTER:用于用户向SIP服务器传送位置信息或地址信息。
CANCEL:取消当前的请求,但它并不能中止已经建立的连接。
状态行(Status-Line)
响应消息的起始行,SIP应答消息的Status-Line由SIP-Version开始,接着是一个数字编码的状态码Status-Code,最后是一个与状态码相关的描述性短语Reason-Phrase,然后由一个CRLF行结束符结束Status-Line。
SIP应答消息的六类应答状态编码
1xx:临时消息:表示表示请求消息已经收到,后面将继续处理该请求。
2xx:成功消息:表示请求已经被成功的理解、接受或执行。
3xx:重定向消息:表示为了完成请求还需采取更进一步的动作。
4xx:客户机错误:表示该请求含有语法错误或在这个服务器上不能被满足。
5xx:服务器错误:表示该服务器不能处理一个明显有效的请求。
6xx:全局性故障:表示该请求在任何服务器上都不能被实现。
消息头
消息头的作用是进一步提供有关消息的其他信息,使代理服务器或客户代理服务器更好地对消息进行处理。消息头分四类:通用头(general-header )、请求头(request-header )、响应头( response-header )和实体头( entityheader)。
-
general-header
描述消息基本属性的通用头域,可用于请求消息和应答消息;
消息头有:Call-ID,From,To,Via,Contact,CSeq,Encryption,Expires,Record-Route,Timestamp,Date,Accept,Accept-Encoding,Accept-Language -
request-header
请求头域,只可用于请求消息,它被用来传递有关应答的附加信息,对请求进行补充说明;
Subject,User-Agent,Organization,Contact,Authorization,Proxy-Authorization,Proxy-Require,Response-Key,Require,Priority,Hide,Route,Max-Forwards。 -
response-header
应答头域,只可用于应答消息,它被用来传递有关应答的附加信息,对应答进行补充说明。
Proxy-Authenticate,WWW-Authenticate,Retry-After,Server,Warning,Allow,Unsupported。 -
entity-header
消息体头域,用于描述消息体内容的长度、格式和编码类型等属性,可用于请求消息或应答消息。
Content-Encoding,Content-Length,Content-Type
消息头格式
每个消息头都是一个“句子”,以CRLF行结束符表示一个头域的结束。它们都由字段名(field-name)和域值(field-value)两部分组成,中间以“:”相隔。
常见消息头说明:
TO:格式:TO:显示名<接收者URI>;tag=n;显示名和tag可选。接收者URI是SIP网络种唯一标识接收终端的标识符。例:TO:DENNYSIP:caller@WORK.COM;TAG=11111 或 TO:sip:caller@work.com
FROM: 消息头FROM给出标识会话发起者的URI。比如:FROM:sip:caller@work.com;tag=hyh8。tag是必需的。
CALL-ID: 用于全局唯一标识正在建立的会话的标识符。 随机数加UAC标识信息。
CSeq: 用于标识同一会话中不同事务的序号,通常由一个用作序号的整型数和消息类型组成。整个会话操作过程由不同的事务组成,每一事务所涉及的消息的CSeq序号必须相同。
Via:为响应消息提供传输路径,当请求消息经过每一跳节点时,每一跳节点都把自身的IP地址信息放入顶层Via中。响应消息则沿着请求消息记录下的传输路径反向传输,首先移走指明自身IP地址信息的顶层消息头.
关于SIP协议中ACK处理机制讨论
参考链接:
1.关于SIP协议中ACK处理机制讨论
一般情况下,在INVITE的完整流程的最后流程中,我们可以看到ACK。但是,有时,我们又没有看到ACK,ACK可能在传输过程中丢失或者根本就没有ACK。如果我们没有最终的ACK消息,怎么能够保证一个完整的可靠性传输呢? 另外,我们在其他的SIP 请求中好像没有看到ACK。在本文章讨论中,笔者专门针对ACK的消息,并且让大家带着这些疑惑对ACK的处理机制进行讨论和大家共同学习。
1、ACK在SIP INVITE中作用
在200 OK传输过程启动时,被呼叫方响应就会启动另外一个定时器来计时。如果对端在超时后没有收到200 OK,则说明200 OK丢失,重新发送,直到呼叫方收到200 OK,然后发送ACK请求,直到被呼叫方最终收到ACK请求消息,确保可靠性传输的完全完成。接下来,我们讨论一下ACK的角色。
2、关于SIP中ACK的疑惑
很多读者可能对ACK有一些疑惑。ACK好像没有自己启动什么流程,不像其他的请求,例如INVITE那样可以启动一个请求。那么,ACK到底是一个request请求还是response响应? 根据RFC3261的对request和response的定义,request定义中规定,请求必须有Method 类型,而response必须以状态码和响应短语构成。在RFC3261 7.1和7.2中有这样的语法规范:
Request:
Request-Line = Method SP Request-URI SP SIP-Version CRLF
responses:
Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
但是,让读者感到迷惑的是,如果是一个request的话,request至少需要启动流程执行什么动作,但是好像ACK并自己启动流程,ACK仅负责发送了响应消息。实际上,ACK也仅负责对可靠性传输的最终确认。因此,无论读者有什么样的迷惑,根据RFC3261的规范,ACK仍然是一个request。
3、ACK本身就是一个transaction(事务)
为什么在INVITE的示例中,ACK是独立的一个transaction呢?为了回答这个问题,我们需要根据RFC3261的规范来说明ACK。 根据SIP transaction-17的定义,一个transaction必须是以request开始,以一个或者多个最终response结束,中间可以支持多个临时响应。
Specifically, a SIP transaction consists of a single request and any responses tothat request, which include zero or more provisional responses andone or more final responses.
但是,在RFC3261-17中,transaction另外有一段对transaction的特别说明,可能一般读者没有注意到这段说明解释。它是这样定义的:
按照这个定义,ACK就可以构成自己独立的transaction,因此,如果满足了以上条件的话(这里的响应是200 OK),那么,ACK本身自己就是一个transaction。
4、仅INVITE中才能看到ACK
在SIP呼叫中,我们为什么只能在INVITE的请求中看到ACK,其他的请求中却没有看到ACK(例如BYE中)?
BYE中则没有看到ACK的出现:
下面,我们解释一下其中的原因。 其实原因也很简单。大部分情况下,INVITE的请求发送以后,电话系统需要人工干预,例如需要等被呼叫方来接听,而其他的请求则无需人工干预,例如BYE和注册。下面,我们解释一下非INVITE请求中为什么没有出现ACK。
BYE请求是一种无ACK的使用场景。如果一方挂机的话,无需另外一方进行人工干预。,例如,被呼叫方仅通过终端自动简单回复200 OK就可以实现整个流程的完整性。
同样,注册也是一样的道理,如果UAC需要对服务器端发送注册请求时,服务器端仅根据注册请求的信息来验证其身份即可,无需进行人工干预。服务器端验证UAC的信息,则会自动返回一个最终响应消息。
但是,如果是INVITE请求的话,则实现的流程完全不同。因为,如果呼叫方发起呼叫以后,对端话机振铃。在振铃时间内,如果被呼叫方不在工作台的话,电话一直振铃,系统需要花费一定时间来等待被呼叫方应答,接听电话,这时是需要人工干预来完成一个可靠性传输过程。当然,用户可以通过一些软交换呼叫路由的设置(SIP头添加alter-info:ring answer),终端电话(设置 Ring Answer)也可以实现呼叫的自动应答,这是另外一个话题。
通过以上例子,我们可以看到,其他的非INVITE都可以通过自动化的处理方式来实现,无需人工干预。因此,只有INVITE中带有ACK请求回复,而没有看到其他的请求中带ACK的请求回复。
最后,ACK的处理机制依赖于最终响应的类型。在UAC发起发起初始化请求,UAC需要对每个最终响应(300-699)发送一个响应消息,但是处理这个ACK的机制完全取决于response的响应类型。在transaction进行处理时遵从具体的规则。关于规则的定义,读者可以查阅REFC3261的17章节。
SIP的NAT穿透方法浅析
1、SIP协议的NAT有四种模型。
a) Full Cone 完全圆锥体
b) restricted cone 受限制的圆锥体
c) port restricted 端口受限制的圆锥体
d) symmetric 对称的
其中a,b,c 也称作非对称的NAT。
2、SIP终端在NAT后面,其工作有可能出现问题。原因是SIP信令走的路径,和媒体流走的路径不一样。
3、Full Cone 完全圆锥体NAT
因特网上的任何PC,可以发送数据包到IP:port对;而NAT将这个IP:port对(公网上的)映射到内网的IP:port对(私有网络的)。
4、restricted cone 受限制的圆锥体NAT
NAT外面的PC,只有那些内网中已有PC与之联系过的PC,才能通过这个映射进来。例如,我通过内网的一台机器,IP 地址是10.1.1.1:123,与PC(a)联系,则PC(a)也可以通过这个NAT的映射,联系到我。而PC(b)则不行。
10.1.1.1:123 ---NAT ---> 202.70.65.78:10000 ------pc(a)
如果pc(b)也发送数据到202.70.65.78:10000,则不会有数据送到10.1.1.1:123。
补充说明:
如果我也联系过pc(b),则pc(b)也可以进来了。
10.1.1.1:123 ---NAT ---> 202.70.65.78:10000 ------pc(b)
如果pc(b)也发送数据到202.70.65.78:10000,则数据送到10.1.1.1:123。
5、port restricted 端口受限制的圆锥体NAT
除了4的条件外,即不但要检测pc(a)的源IP地址,还要检测其端口是否与前面也一样。
10.1.1.1:123 --->NAT---->202.70.65.78:10000 -----> pc(a)[213.123.324.34:8000]
这个NAT只会接收从IP地址 213.123.324.34 且端口为 8000来的数据,让进入到10.1.1.1:123。
6、对称的NAT 这是关系描述最简单的一个
10.1.1.1:1000 ----NAT -----> 200.123.123.34:1234 ----pc(a)
10.1.1.1:1000 ----NAT -----> 200.123.123.34:2222----pc(b)
这种NAT的IP:port对,对每个外部的程序,都是不同的。因而每一个外部的程序,都有自己的映射(NAT分配的IP:port对)。而前面的三种,多个外部程序,可能共用一个NAT的IP:port对。
7、RTP的问题
在RTP的消息正文内,有UA能够成功通信所需要的一些信息。这种消息正文,就叫做SDP消息。
问题在于,SIP终端(UA)可能对NAT一无所知。因而在SDP中包含的IP地址,通常使用内部的IP地址,也就是SIP终端知道的IP。这样,当通信的对方想与SIP终端通信时,就查看SDP消息中的IP地址,但是什么也没有得到,因为这里使用的是内部IP地址。
下面举个例子说明
INVITE sip:040600@192.168.20.2:5060 SIP/2.0.
Record-Route: <sip:143.248.130.35;ftag=3a7ceb24a6ac50c4;lr=on>.
Via: SIP/2.0/UDP 143.248.130.35;branch=z9hG4bK758e.976609c7.0.
Via: SIP/2.0/UDP
192.168.20.3;rport=1024;received=223.178.140.109;branch=z9hG4bK34efcab2403aa20d.
From: "Iqbal" <sip:040618@sip.dom.com>;tag=3a7ceb24a6ac50c4.
To: <sip:040600@sip.dom.com>.
Contact: <sip:040618@223.178.140.109:1024>.
Supported: replaces.
Call-ID: 7f2c327896a5b0e1@192.168.20.3.
CSeq: 8717 INVITE.
User-Agent: Grandstream HT487 1.0.5.18.
Max-Forwards: 16.
Allow: INVITE,ACK,CANCEL,BYE,NOTIFY,REFER,OPTIONS,INFO,SUBSCRIBE.
Content-Type: application/sdp.
Content-Length: 343.
.
v=0.
o=040618 8000 1 IN IP4 192.168.20.3.
s=SIP Call.
c=IN IP4 192.168.20.3.
t=0 0.
m=audio 38660 RTP/AVP 0 8 4 18 2 15 99.
a=sendrecv.
a=rtpmap:0 PCMU/8000/3.
a=rtpmap:8 PCMA/8000/3.
SIP消息的标题头,类似于邮件的标题头。从后往前看,从From行开始,看到第一个Via行,这是SIP终端自己认为的IP地址,例如192.168.20.3。但是SIP代理服务器是聪明的,它知道这个消息是从哪里发过来的,它添加了rport和接收到的标志:
Via: SIP/2.0/UDP
192.168.20.3;rport=1024;received=223.178.140.109;branch=z9hG4bK34efcab2403aa20d.
也就是说,SIP代理服务器,知道发消息的SIP终端的公网地址是223.178.140.109:1024。
这样,SIP代理服务器是可以与SIP终端通信的,因为它知道SIP终端的公网地址。
但是,可怜的老式的RTP被阻塞了,因为它的标题头如下:
v=0.
o=040618 8000 1 IN IP4 192.168.20.3.
s=SIP Call.
c=IN IP4 192.168.20.3.
t=0 0.
m=audio 38660 RTP/AVP 0 8 4 18 2 15 99.
a=sendrecv.
a=rtpmap:0 PCMU/8000/3.
a=rtpmap:8 PCMA/8000/3.
SIP终端期望从端口 port m=38660 且IP地址IP c= 192.168.20.3来接收RTP数据,而这个192.168.20.3:38660,就是通信的对方试图发RTP数据的目的地址。
这就是SIP电话振铃总是能够听到,而接起来却没有声音的原因。
8 解决办法 告诉SIP终端,不要如此傻地工作,而要想办法知道NAT分配给自己的端口映射。
并将公网的IP地址:端口放到SDP消息中。这样,SIP终端就问NAT....。或者是问公网的某个服务器,NAT分配给自己的映射是什么。
9 问NAT。 这种办法就是使用UPnP协议,另外去参见UPnP的资料。
10 问公网上的某个服务器。 如STUN服务器。
SIP终端发送一个探测数据包,到公网上的服务器。公网上的服务器会发回数据包,会包含有关NAT的详细信息。有了这些信息,SIP终端就会知道它是否在NAT后面。这种探测方法,可以用于上面4种NAT,都有效。例如SIP终端从10.1.1.1:1000发送一个数据包,则SDP消息中包含的是m=1000 and c=10.1.1.1。但是,如果SIP终端先进行NAT探测,则会知道NAT会分配公网的IP:端口是212.134.123.23:12345。则 SIP终端直接在SDP消息写m=12345,c=212.134.123.23。
产生的问题 因为NAT的端口分配是动态的,因而有可能会改变。这样,在发送了NAT探测消息后,要很快地发送出SIP消息。而且,SIP终端发送数据的端口和接收数据的端口要是一样的。
注意受限制的圆锥体(包括端口受限制的圆锥体)NAT,它不让回来的消息进来,除非SIP终端先发了一个数据包给它。因而,SIP终端需要先发一个数据包给对方。这样以后对方来的数据,就可以进入NAT内部了(不过,不需要为这个操作担心,有办法的)。
上面的办法在对称的NAT后面,不能够工作。因为,对称的NAT,它在分配给SIP终端外部的IP:port时,每次都变化(不同的对方不一样)。也就是SIP终端在探测NAT时,得到的IP:port,与它后来发SIP消息时,分配的IP:port不一样。这样,对方来的语音数据就进不来,因为对方得不到正确的IP:port。
11、上面描述的过程,其实就是采用STUN协议时,解决问题的过程。就是SIP终端向STUN服务器发探测NAT的数据包。
12、对称的NAT 解决办法 就是在公网上放一个中转语音流的服务器。这个中转语音流的服务器有时就是一个Out Bound proxy。注意,这个中转语音流的服务器,可能会成为瓶颈。由于语音要经过中转语音流的服务器,所以路径增长了,音质会变差。所以,对称的NAT,要SIP能够工作,总之是个麻烦。
不过,目前大多数的NAT,都可以做“虚拟服务器的端口转发”,即将SIP工作需要的端口转发到SIP终端上去。如果在NAT设备上,做了“虚拟服务器的端口转发”,则NAT会保留SIP工作需要的端口,专用于SIP终端,这样SIP终端就相当于是在一个Full Cone完全圆锥体的NAT后面,SIP用STUN工作没有问题。SIP终端需要的端口数是这样确定的,一个端口用于SIP信令,比如5060。RTP端口的数量,取决于通话的路数。一路通话需要2个RTP端口。每增加一路通话,则需要多2个端口。
只支持一路通话的SIP话机,需要NAT映射3个端口。
前面三种的NAT,可统称为非对称的NAT。非对称的NAT,都可以用STUN协议穿过NAT。
将对称的NAT,通过端口转发的方式,变为完全圆锥体的NAT,是解决NAT问题的最好办法。首先应当用这种办法来解决。没有办法映射端口,再想其它的办法。