SIP协议详解:从请求到挂断的全生命周期
SIP,即Session Initiation Protocol(会话初始协议),是一种应用层控制协议,专为建立、修改及终止多媒体会话而设计,如Internet电话等。它涵盖了五个关键方面:用户定位,用于确认终端用户的位置;用户有效性,旨在检查用户是否愿意参与会话;用户能力,涉及媒体和媒体参数的检测;会话建立,包括“ringing”状态和在呼叫方与被叫方间建立会话参数;以及会话管理,涵盖发送、终止会话,修改会话参数及激活服务等操作。
SIP协议结构

> 消息体结构和请求行
接下来,让我们一同揭开SIP协议格式的神秘面纱。SIP消息结构与HTTP相似,包括请求行、消息头和正文,请求行说明方法和版本。请求行的格式为“Method Request-URI SIP-Version”,而method则包括多种消息方法,如INVITE、ACK等。

> 消息头详细解读
消息头部分包括多个字段,例如Record-Route、Via、Max-Forwards、Call-ID、CSeq、Allow、Supported、User-Agent、Content-Type和Content-Length等。这些字段提供了关于SIP消息的详细信息,如路由记录、传输路径、最大转发次数、呼叫标识、请求序列号、允许的方法、支持的选项、用户代理信息以及消息体的类型和长度等。通过解析这些消息头字段,接收方可以了解消息的来源、目的地、传输方式以及包含的内容等信息,从而正确处理和响应SIP请求或响应。
> 状态码示例
状态行的格式:SIP-Version Status-Code,例如:SIP/2.0 200 OK。接下来,我们将简要介绍一些常见的状态码。

03完整流程案例
> 环境说明
在接下来的案例中,我们将介绍SIP协议的实际应用场景。实验环境中使用了docker、Kamailio和FreeSWITCH容器。本地en0 网卡地址为192.168.31.188,Kamailio的IP为172.18.0.188,代理端口为15060,而FreeSWITCH的IP为172.18.0.1。
> INVITE消息示例
从本地IP地址192.168.31.188发出的INVITE请求,目标分机号为10087。该请求包含具体的字段如Call-ID和CSeq等。在SIP协议中,这样的 INVITE 消息标志着一个新会话的开始。
100 > Trying消息
消息来自FreeSWITCH,表示已收到请求并准备呼叫目标。目标号码正在处理中,该状态通过Via和Call-ID字段信息得到体现。此类消息的Via头域指明了消息的传输路径和接收地址。
183 > Progress消息
在SIP协议中,183 Progress消息表明呼叫正在进行中。这意味着呼叫已从源成功传递到目标端,并且目标端已经接受该呼叫。Freeswitch发送此消息以确认连接正在建立。
200 > OK消息
当电话被接听后,系统会回复一个200 OK的消息给freeswitch,确认呼叫已成功建立。请求成功,且会话已建立。该的消息头部包含了允许的操作,如INVITE、ACK等,以及一系列支持的扩展功能。
> BYE和结束挂断
结束通话时,系统会发送一个BYE消息,携带挂机原因。此消息告知freeswitch某一方决定结束通话,freeswitch收到后会相应地做出响应,确认会话的终止。至此,整个SIP协议的通话流程便宣告结束。
过程描述:
默认端口5060。

用户注册:
用户开机后向服务器发起注册登记(register)来告诉服务器自己已经开机了请帮忙在服务器上给我注册登记。服务器收到电话用户发来的register,发现用户发来register未携带认证信息并回复用户一个401 Unauthorized的状态码(401未授权),同时服务器回生成一个nonce字段来告诉用户后面注册需要携带这些认证信息。用户收到后查看服务器发来的nonce,并将认证所需要的信息带上再次向服务器发出Register。服务器收到用户发来的register并查看是否携带了注册登记所需的信息,都携带了会给用户注册登记上服务器并给用户回复一个200 OK

呼叫流程:
呼出失败:
用户A想要与用户B建立通话,首先用户A会向服务器发送一个携带ip、电话号码等信息的INVITE with stp1请求,服务器收到后立刻回复用户A一个100 Trying的状态码(100临时响应),告诉用户A已经收到你的请求并已经开始尝试呼叫,接着服务器又给用户A回复一个407的 状态码,同时会携带上一个nonce字段告诉用户A需要携带哪些认证信息。用户A收到服务器发来的状态码后给服务器回了一个ACK确认(注:每一个INVITE请求都会以一个ACK最后确认)。
呼出成功:
接呼出失败,通过407的状态码用户A知道了服务器所需要的认证信息,然后携带上所需信息重新向服务器发起INVITE,服务器收到后立刻回复一个100 Trying的状态码(100 临时响应),告诉用户A已经收到你的请求并已经开始尝试呼叫。然后服务器就开始匹配用户B的信息,匹配成功后直接向用户B转发用户A的请求,用户B收到请求后也会向服务器发送一个100 Trying状态码,告诉服务器已经收到发来的请求。接着用户B还会发送一个180 Tinging的状态码(正在振铃),表示已经开始振铃。服务器收到用户B的180 Tinging后也会向用户A发送一个 180 Trying来告诉用户A,用户B已经振铃了,这时表示用户A和用户B 的连接都没有问题,于是都向服务器发送一个200 OK的状态码。最后用户A和用户B处理完INVITE最终会发送一个ACK确认。

挂断流程:
通话需要结束时,用户A会先发送一个BYB请求消息给服务器,通知服务器已经挂断电话,服务器收到消息后回回复一个200 OK for byb的状态码,同时服务器发送BYB消息告诉用户B用户A已经挂断,用户B收到后会回复服务器一个200 OK for byb的状态码表示确认挂断。

