zoukankan      html  css  js  c++  java
  • SIP 协议详解

    SIP 协议详解

    2013年参与过一个“视频通讯的App”项目,使用Sip协议通信。当时通信协议这块不是自己负责,加上时间紧、任务重等方面的原因,一直未对Sip协议进行过深入的了解。
    2020年春天疫情突发,宅在家里终于有了空余时间。这里来详细了解一下Sip协议。

    以下内容大致分为以下几个部分:

    • 协议简介
    • 两种Sip会话模式Session Model与Pager Model;
    • Sip 消息体结构
    • Sip 消息举例

    一、Sip协议简介:

    SIP(Session Initiation Protocol,会话初始协议)是由IETF(Internet Engineering Task Force,因特网工程任务组)制定的多媒体通信协议。广泛应用于CS(Circuit Switched,电路交换)、NGN(Next Generation Network,下一代网络)以及IMS(IP Multimedia Subsystem,IP多媒体子系统)的网络中,可以支持并应用于语音、视频、数据等多媒体业务,同时也可以应用于Presence(呈现)、Instant Message(即时消息)等特色业务。可以说,有IP网络的地方就有SIP协议的存在。
    SIP是类似于HTTP,SIP可以减少应用特别是高级应用的开发时间。由于基于IP协议的SIP利用了IP网络,固定网运营商也会逐渐认识到SIP技术对于他们的远意义。

    二、Sip消息的两种会话模式

    在Sip IM通信应用过程中,一般存在着两种会话模式:

    • Session Model
    • Pager Model

    2.1、Session Model

    会话中,对于消息体内容大于1300字节时,一般采用Session Model。其会话建立过程如下图所示:

     SIP协议Session Model

    主叫方A呼叫被叫方B:

    • 步骤1:主叫方A发送INVITE请求到代理服务器
    • 步骤2:代理服务器发送100 Trying 响应主叫方A
    • 步骤3~6:代理服务器搜索被叫方B的地址,获取地址后转发INVITE请求;
    • 步骤7~9:被叫方B生成的180 振铃响应,返回给主叫方A
    • 步骤10~12:被叫方B生成的200 OK响应,返回给主叫方A
    • 步骤13~17:主叫方A收到被叫方B200 OK响应后,向被叫方B发送一个ACK,会话建立;
    • 步骤18~20:会话结束后,任何参与者(A或B)都可以发送一个BYE请求来终止会话;
    • 步骤21~23:主叫方A发送200 OK响应来确认BYE,会话终止。

    注:以上的整个流程称之为一个Dialog

    2.2、Pager Model

    在Sip消息中,对于消息体不大于1300字节时,一般采用Pager Model。Sip消息通信中采用MESSAGE方法,MESSAGE方法本身并不建立Dialog,在多数应用中,每条IM消息都是独立的,颇似分页消息。

    2.2.1 MESSAGE方法的由来

    RFC3428对Sip协议进行了扩展,在Sip协议中增加了MESSAGE请求方法。采用Pager Model进行通信,传递不超过1300字节的数据。MESSAGE方法详细可参考 “SIP-RFC3428” https://tools.ietf.org/html/rfc3428

    2.2.2 MESSAGE方法消息体

    当User1想给User2发送IM消息时,只需构造一个MESSAGE,发出去即可。
    对于其消息体body可以是任何MIME格式。但必须支持plain/text格式,可以选择支持message/cpimmessage/sdp格式,可能用message/cpim会好一点,因为已有的IM系统标准是message/cpim格式。

    注:想了解CPIM消息格式的同学可参考:CPIM 消息格式:https://xiaxl.blog.csdn.net/article/details/104718006
    注:想了解SDP消息格式的同学可参考:SDP 消息格式:https://xiaxl.blog.csdn.net/article/details/104723834

    2.2.3 Pager Model请求流程如下

    以User1向User2发送MESSAGE消息为例:

    Pager Model

    • 步骤1:User1发送MESSAGE请求到代理服务器
    • 步骤2:代理服务器转发User1的MESSAGE请求给USER2
    • 步骤3:User2收到User1的消息后,回复200 OK给代理服务器
    • 步骤7~9:代理服务器转发200 OK回复给User1

    三、SIP消息体格式

    SIP消息体结构Http协议结构相似,均由三部分组成:

    • 请求行(request-line) or 状态行(status-line)
    • 消息头(header)
    • 正文(body)

    3.1、请求行

    请求行格式:Method Request-URI SIP-Version CRLF
    请求行举例:INVITE sip:bob@zte.com SIP/2.0 /r/n

    Method
    以下列出了几种消息Method方法

    Method方法说明
    REGISTER 注册联系信息
    INVITE 发起会话请求
    ACK INVITE 请求的响应的确认
    CANCEL 取消请求
    BYE 终结会话
    OPTIONS 查询服务器能力
    MESSAGE RFC3428对Sip协议的扩展,增加了MESSAGE方法。采用Pager Model进行通信,传递不超过1300字节的数据。MESSAGE方法详细可参考 “SIP-RFC3428” https://tools.ietf.org/html/rfc3428

    Request-URI
    指示请求的用户或者服务的地址信息

    SIP-Version
    请求和响应消息都需要包含SIP版本信息

    3.2、状态行

    状态行格式: SIP-Version Status-Code Reason-Phrase CRLF
    状态行举例:SIP/2.0 200 OK /r/n

    Status-Code状态码:
    状态代码由3位数字组成,表示请求是否被理解或被满足。
    状态代码的第一个数字定义了响应的类别,后面两位没有具体的分类

    第一个数字有五种可能的取值:

    状态码含义
    1xx: 临时响应、表示请求消息正在被处理
    2xx 成功响应、表示请求已被成功接收完全理解并接收
    3xx 重定向响应、表示需采取进一步完成请求
    4xx 客户机错误、表示请求消息中包含语法错误信息或服务器无法完成客户机的请求
    5xx 服务器错误、表示服务器无法合法完成请求
    6xx 全局故障 、表示任何服务器都无法完成该请求

    常用的状态码举例:

    状态码msg含义
    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 全忙

    3.3、消息头

    发送MESSAGE消息给user2

    MESSAGE sip:user2@domain.com SIP/2.0
    Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse
    Max-Forwards: 70
    From: sip:user1@domain.com;tag=49583
    To: sip:user2@domain.com
    Call-ID: asd88asd77a@1.2.3.4
    CSeq: 1 MESSAGE
    Content-Type: text/plain
    Content-Length: 18
    
    user2, come here.
    

    Header 字段含义说明:

    Header含义说明举例
    Call-ID 由本地设备(Client)生成,全局唯一,每次呼叫这个值唯一不变 Call-ID: asd88asd77a@1.2.3.4
    From 表示请求的发起者 From: sip:user1@domain.com;tag=49583
    To 表示请求的接收者 To: sip:user2@domain.com
    Via Via头域是被服务器插入request中,用来检查路由环的,并且可以使response根据via找到返回的路 Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse
    Max-Forwards 用于表示这个包最多可以传送多少跳,每经过一跳都会减一当Max-Forwards==0系统会返回483。默认为70 Max-Forwards: 70
    Contact 包含源的URI信息,用来给响应方直接和源建立连接用 Contact: sip:192.168.100.1:1111
    Content-Type 指明消息体的类型 (SDP会话描述协议) Content-Type: text/plain;Content-Type: application/sdp; Content-Type: application/cpim;
    Content-Length 指明消息体的字节大小 Content-Length: 18

    四、SIP消息举例

    这里举两个例子:

    • MESSAGE消息(Pager Mode)
    • REGISTER消息

    4.1、MESSAGE消息(Pager Model)

    User1发送MESSAGE消息给user2为例:

    Pager Model

    步骤1:User1发送MESSAGE请求到代理服务器
    MESSAGE sip:user2@domain.com SIP/2.0
    
    Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse
    Max-Forwards: 70
    From: sip:user1@domain.com;tag=49583
    To: sip:user2@domain.com
    Call-ID: asd88asd77a@1.2.3.4
    CSeq: 1 MESSAGE
    Content-Type: text/plain
    Content-Length: 18
    
    user2, come here.
    
    步骤2:代理服务器转发User1的MESSAGE请求给USER2

    代理服务器收到步骤1请求,到数据库中查找User2(注册过程中生成数据库),随后生成步骤2的数据。

    
    MESSAGE sip:user2@domain.com SIP/2.0
    Via: SIP/2.0/TCP proxy.domain.com;branch=z9hG4bK123dsghds
    Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse;
                                                  received=1.2.3.4
    Max-Forwards: 69
    From: sip:user1@domain.com;tag=49394
    To: sip:user2@domain.com
    Call-ID: asd88asd77a@1.2.3.4
    CSeq: 1 MESSAGE
    Content-Type: text/plain
    Content-Length: 18
    
    user2, come here.
    
    步骤3:User2收到User1的消息后,回复200 OK给代理服务器

    直接回应(200-OK) 没有Body,也不携带Contact头域

    SIP/2.0 200 OK
    Via: SIP/2.0/TCP proxy.domain.com;branch=z9hG4bK123dsghds;
                                                received=192.0.2.1
    Via: SIP/2.0/TCP user1pc.domain.com;;branch=z9hG4bK776sgdkse;
                                                   received=1.2.3.4
    From: sip:user1@domain.com;tag=49394
    To: sip:user2@domain.com;tag=ab8asdasd9
    Call-ID: asd88asd77a@1.2.3.4
    CSeq: 1 MESSAGE
    Content-Length: 0
    
    步骤4:代理服务器转发200 OK回复给User1

    代理服务器收到回复后,去掉最顶端的Via,转发如下消息给User1

    SIP/2.0 200 OK
    
    Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse;
                                                  received=1.2.3.4
    From: sip:user1@domain.com;;tag=49394
    To: sip:user2@domain.com;tag=ab8asdasd9
    Call-ID: asd88asd77a@1.2.3.4
    CSeq: 1 MESSAGE
    Content-Length: 0
    

    4.2、REGISTER消息

    首先举例一个非鉴权注册消息。

    4.2.1 非鉴权注册消息

    192.168.2.161机器发送注册消息给192.168.2.89服务器:

    REGISTER sip:192.168.2.89 SIP/2.0
    
    Via: SIP/2.0/UDP 192.168.2.161:10586
    Max-Forwards: 70
    From: <sip:01062237496@192.168.2.89>;tag=ca04c1391af3429491f2c4dfbe5e1b2e;epid=4f2e395931
    To: <sip:01062237496@192.168.2.89>
    Call-ID: da56b0fab5c54398b16c0d9f9c0ffcf2@192.168.2.161
    CSeq: 1 REGISTER
    Contact: <sip:192.168.2.161:10586>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER"
    User-Agent: RTC/1.2.4949 (BOL SIP Phone 1005)
    Event: registration
    Allow-Events: presence
    Content-Length: 0
    

    当注册成功(回送200 OK)时,服务器发送的res消息参考如下:

    SIP/2.0 200 OK
    
    Via: SIP/2.0/UDP 192.168.2.161:10586
    From: <sip:01062237496@192.168.2.89>;tag=ca04c1391af3429491f2c4dfbe5e1b2e;epid=4f2e395931
    To: <sip:01062237496@192.168.2.89>;tag=-00834-14d0805b62bc026d
    Call-ID: da56b0fab5c54398b16c0d9f9c0ffcf2@192.168.2.161
    CSeq: 1 REGISTER
    Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,REGISTER,INFO,UPDATE,PRACK,REFER,SUBSCRIBE,NOTIFY,MESSAGE
    Contact: sip:192.168.2.161:10586
    Content-Length: 0
    Expires: 3600
    
    4.2.2 鉴权注册消息

    当需要鉴权注册时

    • 请求端192.168.2.161发送注册消息给192.168.2.89服务器
    • 服务器对192.168.2.161发送“401 Unauthorized”信息给请求端,提示请求端需要带上鉴权信息重新注册
    • 请求端带上鉴权信息后(带有“Authorization”头字段)重新向服务器注册
    • 服务器验证鉴权头的正确性,如果鉴权成功,给请求端发送200 OK消息。若失败,继续发送401消息。

    请求端192.168.2.161发送注册消息给192.168.2.89服务器

    REGISTER sip:192.168.2.89 SIP/2.0
    
    Via: SIP/2.0/UDP 192.168.2.161:8021
    Max-Forwards: 70
    From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
    To: <sip:01062237493@192.168.2.89>
    Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
    CSeq: 1 REGISTER
    Contact: <sip:192.168.2.161:8021>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER"
    User-Agent: RTC/1.2.4949 (BOL SIP Phone 1005)
    Event: registration
    Allow-Events: presence
    Content-Length: 0
    

    服务器对192.168.2.161发送401 Unauthorized信息给请求端,提示请求端需要带上鉴权信息重新注册:

    SIP/2.0 401 Unauthorized
    
    Via: SIP/2.0/UDP 192.168.2.161:8021
    From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
    To: <sip:01062237493@192.168.2.89>;tag=-001893-38ba013ba3dde36e
    Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
    CSeq: 1 REGISTER
    Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,REGISTER,INFO,UPDATE,PRACK,REFER,SUBSCRIBE,NOTIFY,MESSAGE
    Contact: <sip:192.168.2.89:14010>
    Content-Length: 0
    WWW-Authenticate: Digest realm="192.168.2.89", qop="auth", nonce="e17d377c3d2d9c343e26576a7fd04738481dfc10", opaque="", stale=FALSE, algorithm=MD5
    

    请求端192.168.2.161通过Authorization头字段带上鉴权头信息,发送一个新的REGISTER消息:

    REGISTER sip:192.168.2.89 SIP/2.0
    
    Via: SIP/2.0/UDP 192.168.2.161:8021
    Max-Forwards: 70
    From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
    To: <sip:01062237493@192.168.2.89>
    Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
    CSeq: 2 REGISTER
    Contact: <sip:192.168.2.161:8021>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER"
    User-Agent: RTC/1.2.4949 (BOL SIP Phone 1005)
    Authorization: Digest username="01062237493", realm="192.168.2.89", qop=auth, algorithm=MD5, uri="sip:192.168.2.89", nonce="e17d377c3d2d9c343e26576a7fd04738481dfc10", nc=00000001, cnonce="12660455546344082314666316435946", response="f57e47ce03162293b9ced07362ce2b79"
    Event: registration
    Allow-Events: presence
    Content-Length: 0
    

    服务器验证鉴权头的正确性,如果鉴权成功,给请求端发送200 OK消息。若失败,继续发送401消息

    SIP/2.0 200 OK
    
    Via: SIP/2.0/UDP 192.168.2.161:8021
    From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
    To: <sip:01062237493@192.168.2.89>;tag=-001894-a5eb977c8969aa51
    Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
    CSeq: 2 REGISTER
    Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,REGISTER,INFO,UPDATE,PRACK,REFER,SUBSCRIBE,NOTIFY,MESSAGE
    Contact: sip:192.168.2.161:8021
    Content-Length: 0
    Expires: 3600
    

    五、参考:

    Sip—RFC3428:https://tools.ietf.org/html/rfc3428

    MSRP—RFC4975:https://tools.ietf.org/html/rfc4975

    CPIM消息格式:https://www.xuebuyuan.com/1929719.html

  • 相关阅读:
    推荐系统算法总结(转)
    【算法题】求最大子数组之和
    jQuery中的filter和find函数
    获取文件夹大小
    微博140字,英文算半个字,中文算一个字,如何实现?
    Xcode 4 添加 Three20 的方法
    應用程式的設定檔info.plist
    iphone中结束电话后返回自己的应用
    解决问题:The icon file must be 57x57 pixels, in .png format (19014)
    开发中的一些小细节代码分享
  • 原文地址:https://www.cnblogs.com/cnhk19/p/15066093.html
Copyright © 2011-2022 走看看