当前位置:   article > 正文

网络流媒体(七)———RTSP_rtsp视频流

rtsp视频流

RTSP协议介绍

RTSP协议的一些分析(一)———————一些字符串函数的使用

RTSP协议的一些分析(二)———————printf类似函数、sscanf以及log保存到内存中(printf输入重定位)

1 简介

        DSP产生的媒体流需要通过网络传送到客户端,如图1.1所示为媒体流网络传输示意图,RTSP用于完成服务器与客户端之间的消息交互,RTP用于传递媒体流。RTSP使用TCP协议传输,RTP使用UDP协议传输。

        如图1.2所示为RTSP消息交互流程:1. 创建RTSP套接字。2. 等待客户端连接。3. 接收RTSP消息请求。4. 对不同的请求作出相应的处理。5. 发送RTSP消息响应。6. 是否结束会话。7. 若结束会话,则释放资源。
        RTSP请求包括:OPTIONS,DESCRIBE,SETUP,PLAY,GET_PARAMETER,TEARDOWN。服务器接收到OPTIONS请求后,将服务器能够提供的消息传给客户端。服务器接收到DESCRIBE请求后,将SDP信息传给客户端。服务器接收到SETUP请求后,建立RTP套接字,连接客户端RTP端口,等待发送RTP包。服务器接收到PALY请求后,开始发送RTP包。服务器接收到GET_PARAMETER请求后,将当前时间传递给客户端。服务器接收到TEARDOWN请求后,停止发送RTP包,释放资源,停止接收RTSP请求,进入等待客户端连接状态。

         如图1.3所示为传输RTP包流程:1. 当接收到SETUP请求后,创建RTP套接字。2. 连接客户端,等待发送RTP包。3. 当接收到PLAY命令后,开始发送RTP包。4. 当接收到TEARDOWN请求后,关闭RTP套接字,释放资源。

        RTSP(Real Time Streaming Protocol)是由Real Network和Netscape共同提出的如何有效地在IP网络上传输流媒体数据的应用层协议。RTSP对流媒体提供了诸如暂停,快进等控制,而它本身并不传输数据,RTSP的作用相当于流媒体服务器的远程控制。服务器端可以自行选择使用TCP或UDP来传送串流内容,它的语法和运作跟HTTP 1.1类似,但并不特别强调时间同步,所以比较能容忍网络延迟。RTSP与RTP最大的区别在于:RTSP是一种双向实时数据传输协议,它允许客户端向服务器端发送请求,如回放、快进、倒退等操作。当然,RTSP可基于RTP来传送数据,还可以选择TCP、UDP、组播UDP等通道来发送数据,具有很好的扩展性。它时一种类似与http协议的网络应用层协议。

         RTSP处于应用层,而RTP/RTCP处于传输层。RTSP负责建立以及控制会话,RTP负责多媒体数据的传输。而RTCP是一个实时传输控制协议,配合RTP做控制和流量监控。封装发送端及接收端(主要)的统计报表。这些信息包括丢包率,接收抖动等信息。发送端根据接收端的反馈信息做响应的处理。RTP与RTCP相结合虽然保证了实时数据的传输,但也有自己的缺点。最显著的是当有许多用户一起加入会话进程的时候,由于每个参与者都周期发送RTCP信息包,导致RTCP包泛滥(flooding)。
         而且允许同时多个串流需求控制(Multicast),除了可以降低服务器端的网络用量,还可以支持多方视频会议(Video  onference)。 因为与HTTP1.1的运作方式相似,所以代理服务器《Proxy》的快取功能《Cache》也同样适用于RTSP,并因RTSP具有重新导向功能,可视实际负载情况来转换提供服务的服务器,以避免过大的负载集中于同一服务器而造成延迟。
         RTSP(Real-Time Stream Protocol)协议是一个基于文本的多媒体播放控制协议,属于应用层。RTSP以客户端方式工作,对流媒体提供播放、暂停、后退、前进等操作。该标准由IETF指定,对应的协议是RFC2326。
         RTSP作为一个应用层协议,提供了一个可供扩展的框架,使得流媒体的受控和点播变得可能,它主要用来控制具有实时特性的数据的发送,但其本身并不用于传送流媒体数据,而必须依赖下层传输协议(如RTP/RTCP)所提供的服务来完成流媒体数据的传送。RTSP负责定义具体的控制信息、操作方法、状态码,以及描述与RTP之间的交互操作。RTSP媒体服务协议框架如下:

        RTSP包含Normal RTSP(数据通过RTP传输,应用厂商有苹果和微软等),以及Real-RTSP(数据通过RDT传输)。本篇我们主要讲Normal RTSP。
        RTSP传输的一般是TS、MP4格式的流,其传输一般需要2~3个通道,命令和数据通道分离。使用RTSP协议传输流媒体数据需要有专门的媒体播放器和媒体服务器,也就是需要支持RTSP协议的客户端和服务器。

客户端要播放RTSP媒体流,就需要知道媒体源的URL,RTSP的URL格式一般如下:
        rtsp://host[:port]/[abs_path]/content_name
       @host: 有效的域名或IP地址;
       @port: 端口号,缺省为554,若为缺省可不填写,否则必须写明。
       例如,一个完整的RTSP URL可写为:
       rtsp://192.168.1.67:554/test
       又如目前市面上常用的海康网络摄像头的RTSP地址格式为:
       rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream
      示例: 
       rtsp://admin:12345@192.168.1.67:554/h264/ch1/main/av_stream
       rtsp://admin:12345@192.168.1.67/mpeg4/ch1/sub/av_stream

2 RTSP报文 

        对RTSP协议的使用有了一个大概的了解之后,我们来看一下RTSP报文结构。
        RTSP是一种基于文本的协议,用CRLF(回车换行)作为每一行的结束符,其好处是,在使用过程中可以方便地增加自定义参数,也方便抓包分析。从消息传送方向上来分,RTSP的报文有两类:请求报文和响应报文。请求报文是指从客户端向服务器发送的请求(也有少量从服务器向客户端发送的请求),响应报文是指从服务器到客户端的回应。
请求消息:

  1. 方法 URI RTSP版本 CR LF
  2. 消息头 CR LF CR LF
  3. 消息体 CR LF

回应消息:

  1. RTSP版本 状态码 解释 CR LF
  2. 消息头 CR LF CR LF
  3. 消息体 CR LF

       RTSP请求报文的常用方法与作用:

       首先客户端连接到流媒体服务器并发送一个RTSP描述请求(DESCRIBE request),服务器通过一个SDP(Session DescriptionProtocol)描述来进行反馈(DESCRIBEresponse),反馈信息包括流数量、媒体类型等信息。客户端分析该SDP描述,并为会话中的每一个流发送一个RTSP连接建立请求(SETUPrequest),该命令会告诉服务器用于接收媒体数据的端口,服务器响应该请求(SETUP response)并建立连接之后,就开始传送媒体流(RTP包)到客户端。在播放过程中客户端还可以向服务器发送请求来控制快进、快退和暂停等。最后,客户端可发送一个终止请求(TEARDOWN request)来结束流媒体会话。
       下面我们通过具体的消息实例来进一步了解一下RTSP的工作过程:

2.1 OPTIONS

       OPTIONS请求是客户端向服务器询问可用的方法,请求和回复实例如下:

  1. C->S:  OPTIONS rtsp://example.com/media.mp4 RTSP/1.0
  2.        CSeq: 1
  3.        Require: implicit-play
  4.        Proxy-Require: gzipped-messages
  5.  
  6. S->C:  RTSP/1.0 200 OK
  7.        CSeq: 1
  8.        Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE

2.2 DESCRIBE

        客户端向服务器请求媒体资源描述,服务器端通过SDP(Session Description Protocol)格式回应客户端的请求。资源描述中会列出所请求媒体的媒体流及其相关信息,典型情况下,音频和视频分别作为一个媒体流传输。实例如下:

  1. C->S: DESCRIBE rtsp://example.com/media.mp4 RTSP/1.0
  2.       CSeq: 2
  3.  
  4. S->C: RTSP/1.0 200 OK
  5.       CSeq: 2
  6.       Content-Base: rtsp://example.com/media.mp4
  7.       Content-Type: application/sdp
  8.       Content-Length: 460
  9.  
  10.       m=video 0 RTP/AVP 96
  11.       a=control:streamid=0
  12.       a=range:npt=0-7.741000
  13.       a=length:npt=7.741000
  14.       a=rtpmap:96 MP4V-ES/5544
  15.       a=mimetype:string;"video/MP4V-ES"
  16.       a=AvgBitRate:integer;304018
  17.       a=StreamName:string;"hinted video track"
  18.       m=audio 0 RTP/AVP 97
  19.       a=control:streamid=1
  20.       a=range:npt=0-7.712000
  21.       a=length:npt=7.712000
  22.       a=rtpmap:97 mpeg4-generic/32000/2
  23.       a=mimetype:string;"audio/mpeg4-generic"
  24.       a=AvgBitRate:integer;65790
  25.       a=StreamName:string;"hinted audio track"

2.3 SETUP

        SETUP请求确定了具体的媒体流如何传输,该请求必须在PLAY请求之前发送。SETUP请求包含媒体流的URL和客户端用于接收RTP数据(audio or video)的端口以及接收RTCP数据(meta information)的端口。服务器端的回复通常包含客户端请求参数的确认,并会补充缺失的部分,比如服务器选择的发送端口。每一个媒体流在发送PLAY请求之前,都要首先通过SETUP请求来进行相应的配置。

  1. C->S: SETUP rtsp://example.com/media.mp4/streamid=0 RTSP/1.0
  2.       CSeq: 3
  3.       Transport: RTP/AVP;unicast;client_port=8000-8001
  4.  
  5. S->C: RTSP/1.0 200 OK
  6.       CSeq: 3
  7.       Transport:RTP/AVP;unicast;client_port=8000-8001;server_port=9000-9001;ssrc=1234ABCD
  8.       Session: 12345678

2.4 PLAY

         客户端通过PLAY请求来播放一个或全部媒体流,PLAY请求可以发送一次或多次,发送一次时,URL为包含所有媒体流的地址,发送多次时,每一次请求携带的URL只包含一个相应的媒体流。PLAY请求中可指定播放的range,若未指定,则从媒体流的开始播放到结束,如果媒体流在播放过程中被暂停,则可在暂停处重新启动流的播放。

  1. C->S: PLAY rtsp://example.com/media.mp4 RTSP/1.0
  2.       CSeq: 4
  3.       Range: npt=5-20
  4.       Session: 12345678
  5.  
  6. S->C: RTSP/1.0 200 OK
  7.       CSeq: 4
  8.       Session: 12345678
  9.       RTP-Info: url=rtsp://example.com/media.mp4/streamid=0;seq=9810092;rtptime=3450012

2.5 PAUSE

         PAUSE请求会暂停一个或所有媒体流,后续可通过PLAY请求恢复播放。PAUSE请求中携带所请求媒体流的URL,若参数range存在,则指明在何处暂停,若该参数不存在,则暂停立即生效,且暂停时长不确定。

  1. C->S: PAUSE rtsp://example.com/media.mp4 RTSP/1.0
  2.       CSeq: 5
  3.       Session: 12345678
  4.  
  5. S->C: RTSP/1.0 200 OK
  6.       CSeq: 5
  7.       Session: 12345678

2.6 TEARDOWN

        结束会话请求,该请求会停止所有媒体流,并释放服务器上的相关会话数据。

  1. C->S: TEARDOWN rtsp://example.com/media.mp4 RTSP/1.0
  2.       CSeq: 8
  3.       Session: 12345678
  4.  
  5. S->C: RTSP/1.0 200 OK
  6.       CSeq: 8

2.7 GET_PARAMETER

        检索指定URI数据中的参数值。不携带消息体的GET_PARAMETER可用来测试服务器端或客户端是否可通(类似ping的功能)。

  1. S->C: GET_PARAMETER rtsp://example.com/media.mp4 RTSP/1.0
  2.       CSeq: 9
  3.       Content-Type: text/parameters
  4.       Session: 12345678
  5.       Content-Length: 15
  6.  
  7.       packets_received
  8.       jitter
  9.  
  10. C->S: RTSP/1.0 200 OK
  11.       CSeq: 9
  12.       Content-Length: 46
  13.       Content-Type: text/parameters
  14.  
  15.       packets_received: 10
  16.       jitter: 0.3838

2.8 SET_PARAMETER

         用于设置指定媒体流的参数。

  1. C->S: SET_PARAMETER rtsp://example.com/media.mp4 RTSP/1.0
  2.       CSeq: 10
  3.       Content-length: 20
  4.       Content-type: text/parameters
  5.  
  6.       barparam: barstuff
  7.  
  8. S->C: RTSP/1.0 451 Invalid Parameter
  9.       CSeq: 10
  10.       Content-length: 10
  11.       Content-type: text/parameters
  12.  
  13.       barparam

2.9 REDIRECT

         重定向请求,用于服务器通知客户端新的服务地址,客户端需要向这个新地址重新发起请求。重定向请求中可能包含Range参数,指明重定向生效的时间。客户端若需向新服务地址发起请求,必须先teardown当前会话,再向指定的新主机setup一个新的会话。

  1. S->C: REDIRECT rtsp://example.com/media.mp4 RTSP/1.0
  2.       CSeq: 11
  3.       Location: rtsp://bigserver.com:8001
  4.       Range: clock=19960213T143205Z-

2.10 ANNOUNCE

         ANNOUNCE请求有两个用途:(1)C->S:客户端向服务器端发布URL指定的媒体信息描述;(2) S->C:实时更新对话描述。若媒体表示中新增了一个媒体流,例如在直播过程中,则整个媒体表示的description都要被重新发送,而不是只发送新增部分。

  1. C->S: ANNOUNCE rtsp://example.com/media.mp4 RTSP/1.0
  2.       CSeq: 7
  3.       Date: 23 Jan 1997 15:35:06 GMT
  4.       Session: 12345678
  5.       Content-Type: application/sdp
  6.       Content-Length: 332
  7.  
  8.       v=0
  9.       o=mhandley 2890844526 2890845468 IN IP4 126.16.64.4
  10.       s=SDP Seminar
  11.       i=A Seminar on the session description protocol
  12.       u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps
  13.       e=mjh@isi.edu (Mark Handley)
  14.       c=IN IP4 224.2.17.12/127
  15.       t=2873397496 2873404696
  16.       a=recvonly
  17.       m=audio 3456 RTP/AVP 0
  18.       m=video 2232 RTP/AVP 31
  19.  
  20. S->C: RTSP/1.0 200 OK
  21.       CSeq: 7

2.11 RECORD

        请求录制指定范围的媒体数据,请求中可指定录制的起止时间戳;若未指定时间范围,则使用presentation description中的开始和结束时间,这种情况下,如果会话已开始,则立即启动录制操作。

  1. C->S: RECORD rtsp://example.com/media.mp4 RTSP/1.0
  2.       CSeq: 6
  3.       Session: 12345678
  4.  
  5. S->C: RTSP/1.0 200 OK
  6.       CSeq: 6
  7.       Session: 12345678

2.12 EXAMPLE

        以上就是RTSP中常用的命令及其实例介绍。最后,来看一段实际使用的RTSP命令交互过程,该过程是通过PC对海康摄像头视频流的拉取和播放,并通过Wireshark抓取客户端的数据得到的:

  1. OPTIONS rtsp://10.3.8.202:554 RTSP/1.0
  2. CSeq: 2
  3. User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
  4.  
  5. RTSP/1.0 200 OK
  6. CSeq: 2
  7. Public: OPTIONS, DESCRIBE, PLAY, PAUSE, SETUP, TEARDOWN, SET_PARAMETER, GET_PARAMETER
  8. Date:  Mon, Jan 29 2018 16:56:47 GMT
  9.  
  10. DESCRIBE rtsp://10.3.8.202:554 RTSP/1.0
  11. CSeq: 3
  12. User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
  13. Accept: application/sdp
  14.  
  15. RTSP/1.0 401 Unauthorized
  16. CSeq: 3
  17. WWW-Authenticate: Digest realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", stale="FALSE"
  18. Date:  Mon, Jan 29 2018 16:56:47 GMT
  19.  
  20. DESCRIBE rtsp://10.3.8.202:554 RTSP/1.0
  21. CSeq: 4
  22. Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554", response="3fc4b15d7a923fc36f32897e3cee69aa"
  23. User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
  24. Accept: application/sdp
  25.  
  26. RTSP/1.0 200 OK
  27. CSeq: 4
  28. Content-Type: application/sdp
  29. Content-Base: rtsp://10.3.8.202:554/
  30. Content-Length: 551
  31.  
  32. v=0
  33. o=- 1517245007527432 1517245007527432 IN IP4 10.3.8.202
  34. s=Media Presentation
  35. e=NONE
  36. b=AS:5050
  37. t=0 0
  38. a=control:rtsp://10.3.8.202:554/
  39. m=video 0 RTP/AVP 96
  40. c=IN IP4 0.0.0.0
  41. b=AS:5000
  42. a=recvonly
  43. a=x-dimensions:2048,1536
  44. a=control:rtsp://10.3.8.202:554/trackID=1
  45. a=rtpmap:96 H264/90000
  46. a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z00AMp2oCAAwabgICAoAAAMAAgAAAwBlCA==,aO48gA==
  47. a=Media_header:MEDIAINFO=494D4B48010200000400000100000000000000000000000000000000000000000000000000000000;
  48. a=appversion:1.0
  49.  
  50. SETUP rtsp://10.3.8.202:554/trackID=1 RTSP/1.0
  51. CSeq: 5
  52. Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554/", response="ddfbf3e268ae954979407369a104a620"
  53. User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
  54. Transport: RTP/AVP;unicast;client_port=57844-57845
  55.  
  56. RTSP/1.0 200 OK
  57. CSeq: 5
  58. Session:       1273222592;timeout=60
  59. Transport: RTP/AVP;unicast;client_port=57844-57845;server_port=8218-8219;ssrc=5181c73a;mode="play"
  60. Date:  Mon, Jan 29 2018 16:56:47 GMT
  61.  
  62. PLAY rtsp://10.3.8.202:554/ RTSP/1.0
  63. CSeq: 6
  64. Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554/", response="b5abf0b230de4b49d6c6d42569f88e91"
  65. User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
  66. Session: 1273222592
  67. Range: npt=0.000-
  68.  
  69. RTSP/1.0 200 OK
  70. CSeq: 6
  71. Session:       1273222592
  72. RTP-Info: url=rtsp://10.3.8.202:554/trackID=1;seq=65373;rtptime=3566398668
  73. Date:  Mon, Jan 29 2018 16:56:47 GMT
  74.  
  75. GET_PARAMETER rtsp://10.3.8.202:554/ RTSP/1.0
  76. CSeq: 7
  77. Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554/", response="bb2309dcd083b25991c13e165673687b"
  78. User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
  79. Session: 1273222592
  80.  
  81. RTSP/1.0 200 OK
  82. CSeq: 7
  83. Date:  Mon, Jan 29 2018 16:56:47 GMT
  84.  
  85. TEARDOWN rtsp://10.3.8.202:554/ RTSP/1.0
  86. CSeq: 8
  87. Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554/", response="e08a15c27d3daac14fd4b4bcab424a5e"
  88. User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
  89. Session: 1273222592
  90.  
  91. RTSP/1.0 200 OK
  92. CSeq: 8
  93. Session:       1273222592
  94. Date:  Mon, Jan 29 2018 16:57:03 GMT

3. SDP格式

  1. sdp的格式
  2. v=<version>
  3. o=<username> <session id> <version> <network type> <address type> <address>
  4. s=<session name>
  5. i=<session description>
  6. u=<URI>
  7. e=<email address>
  8. p=<phone number>
  9. c=<network type> <address type> <connection address>
  10. b=<modifier>:<bandwidth-value>
  11. t=<start time> <stop time>
  12. r=<repeat interval> <active duration> <list of offsets from start-time>
  13. z=<adjustment time> <offset> <adjustment time> <offset> ....
  14. k=<method>
  15. k=<method>:<encryption key>
  16. a=<attribute>
  17. a=<attribute>:<value>
  18. m=<media> <port> <transport> <fmt list>
  19. v = (协议版本)
  20. o = (所有者/创建者和会话标识符)
  21. s = (会话名称)
  22. i = * (会话信息)
  23. u = * (URI 描述)
  24. e = * (Email 地址)
  25. p = * (电话号码)
  26. c = * (连接信息)
  27. b = * (带宽信息)
  28. z = * (时间区域调整)
  29. k = * (加密密钥)
  30. a = * (0 个或多个会话属性行)
  31. 时间描述:
  32. t = (会话活动时间)
  33. r = * (0或多次重复次数)
  34. 媒体描述:
  35. m = (媒体名称和传输地址)
  36. i = * (媒体标题)
  37. c = * (连接信息 — 如果包含在会话层则该字段可选)
  38. b = * (带宽信息)
  39. k = * (加密密钥)
  40. a = * (0 个或多个媒体属性行)

4 RTSP和HTTP的区别和联系

         联系:两者都用纯文本来发送消息,且rtsp协议的语法也和HTTP类似。Rtsp一开始这样设计,也是为了能够兼容使用以前写的HTTP协议分析代码 。
         区别:rtsp是有状态的,不同的是RTSP的命令需要知道现在正处于一个什么状态,也就是说rtsp的命令总是按照顺序来发送,某个命令总在另外一个命令之前要发送。Rtsp不管处于什么状态都不会去断掉连接。,而http则不保存状态,协议在发送一个命令以后,连接就会断开,且命令之间是没有依赖性的。rtsp协议使用554端口,http使用80端口。

5 RTSP和SIP的区别和联系

          SIP(Session Initiation Protocol),是基于IP的一个应用层控制协议。由于SIP是基于纯文本的信令协议,可以管理不同接入网络上的会话等。会话可以是终端设备之间任何类型的通信,如视频会话、既时信息处理或协作会话。该协议不会定义或限制可使用的业务,传输、服务质量、计费、安全性等问题都由基本核心网络和其它协议处理。
         联系:sip和rtsp都是应用层的控制协议,负责一次通信过程的建立和控制和结束,不负责中间的传输部分。他们都是基于纯文本的信令协议,穿墙性能良好。支持tcp、udp,支持多方通信。他们都需要服务器支持,都支持会话中重定向。sip和rtsp 都使用sdp协议来传送媒体参数,使用rtp(rtcp)协议来传输媒体流。
         区别:rtsp是专门为流媒体制定的协议,在多个媒体流的时间同步方面比sip强大。rtsp还提供网络负载均衡的功能,减轻服务器压力和网络带宽要求。sip一般用来创建一次音频、视频通话(双向),而rtsp一般用来做视频点播、视频监控等(单向)。当然,从原理上讲,rtsp也可以做双向的视频通话。

6 参考文献

网络流媒体协议之——RTSP协议_rtsp流媒体_牧羊女说的博客-CSDN博客 (重要参考文章)

https://www.cnblogs.com/lidabo/p/6553212.html  (有一个java的测试用例)

LIVE555.COM (RTP、RTCP、RTSP、SIP开源)

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号