本博客转载自:https://xiaxl.blog.csdn.net/article/details/104661248
2013年参与过一个“视频通讯的App”项目,使用Sip协议通信。当时通信协议这块不是自己负责,加上时间紧、任务重等方面的原因,一直未对Sip协议进行过深入的了解。 2020年春天疫情突发,宅在家里终于有了空余时间。这里来详细了解一下Sip协议。
以下内容大致分为以下几个部分:
协议简介两种Sip会话模式Session Model与Pager Model;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 IM通信应用过程中,一般存在着两种会话模式:
Session ModelPager Model会话中,对于消息体内容大于1300字节时,一般采用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
在Sip消息中,对于消息体不大于1300字节时,一般采用Pager Model。Sip消息通信中采用MESSAGE方法,MESSAGE方法本身并不建立Dialog,在多数应用中,每条IM消息都是独立的,颇似分页消息。
RFC3428对Sip协议进行了扩展,在Sip协议中增加了MESSAGE请求方法。采用Pager Model进行通信,传递不超过1300字节的数据。MESSAGE方法详细可参考 “SIP-RFC3428” https://tools.ietf.org/html/rfc3428 。
当User1想给User2发送IM消息时,只需构造一个MESSAGE,发出去即可。 对于其消息体body可以是任何MIME格式。但必须支持plain/text格式,可以选择支持message/cpim、message/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
以User1向User2发送MESSAGE消息为例:
步骤1:User1发送MESSAGE请求到代理服务器;步骤2:代理服务器转发User1的MESSAGE请求给USER2;步骤3:User2收到User1的消息后,回复200 OK给代理服务器;步骤7~9:代理服务器转发200 OK回复给User1SIP消息体结构与Http协议结构相似,均由三部分组成:
请求行(request-line) or 状态行(status-line)消息头(header)正文(body)请求行格式:Method Request-URI SIP-Version CRLF 请求行举例:INVITE sip:bob@zte.com SIP/2.0 /r/n
Method 以下列出了几种消息Method方法:
Method方法说明REGISTER注册联系信息INVITE发起会话请求ACKINVITE 请求的响应的确认CANCEL取消请求BYE终结会话OPTIONS查询服务器能力MESSAGERFC3428对Sip协议的扩展,增加了MESSAGE方法。采用Pager Model进行通信,传递不超过1300字节的数据。MESSAGE方法详细可参考 “SIP-RFC3428” https://tools.ietf.org/html/rfc3428Request-URI 指示请求的用户或者服务的地址信息
SIP-Version 请求和响应消息都需要包含SIP版本信息
状态行格式: SIP-Version Status-Code Reason-Phrase CRLF 状态行举例:SIP/2.0 200 OK /r/n
Status-Code状态码: 状态代码由3位数字组成,表示请求是否被理解或被满足。 状态代码的第一个数字定义了响应的类别,后面两位没有具体的分类。
第一个数字有五种可能的取值:
状态码含义1xx:临时响应、表示请求消息正在被处理2xx成功响应、表示请求已被成功接收完全理解并接收3xx重定向响应、表示需采取进一步完成请求4xx客户机错误、表示请求消息中包含语法错误信息或服务器无法完成客户机的请求5xx服务器错误、表示服务器无法合法完成请求6xx全局故障 、表示任何服务器都无法完成该请求常用的状态码举例:
状态码msg含义100Trying试呼叫180Ringing振铃181Call is Being Forwarded呼叫正在前转200OK成功响应302Moved Temporarily临时迁移400Bad Request错误请求401Unauthorized未授权403Forbidden禁止404Not Found用户不存在408Request Timeout请求超时480Temporarily Unavailable暂时无人接听486Busy Here线路忙504Server Time-out服务器超时600Busy Everywhere全忙发送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 Header含义说明举例Call-ID由本地设备(Client)生成,全局唯一,每次呼叫这个值唯一不变Call-ID: asd88asd77a@1.2.3.4From表示请求的发起者From: sip:user1@domain.com;tag=49583To表示请求的接收者To: sip:user2@domain.comViaVia头域是被服务器插入request中,用来检查路由环的,并且可以使response根据via找到返回的路Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkseMax-Forwards用于表示这个包最多可以传送多少跳,每经过一跳都会减一当Max-Forwards==0系统会返回483。默认为70Max-Forwards: 70Contact包含源的URI信息,用来给响应方直接和源建立连接用Contact: sip:192.168.100.1:1111Content-Type指明消息体的类型 (SDP会话描述协议)Content-Type: text/plain;Content-Type: application/sdp; Content-Type: application/cpim;Content-Length指明消息体的字节大小Content-Length: 18这里举两个例子:
MESSAGE消息(Pager Mode)REGISTER消息以User1发送MESSAGE消息给user2为例:
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
直接回应(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代理服务器收到回复后,去掉最顶端的Via,转发如下消息给User1
SIP/2.0 200 OKVia: 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
首先举例一个非鉴权注册消息。
192.168.2.161机器发送注册消息给192.168.2.89服务器:
REGISTER sip:192.168.2.89 SIP/2.0Via: 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 OKVia: 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
当需要鉴权注册时
请求端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.0Via: 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 UnauthorizedVia: 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.0Via: 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
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
</div><div data-report-view="{"mod":"1585297308_001","dest":"https://blog.csdn.net/aiwusheng/article/details/104661248","extend1":"pc","ab":"new"}"><div></div></div> <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e0530931f4.css" rel="stylesheet"> </div>