参考: 手撕RTSP协议系列
rtsp,英文全称 Real Time Streaming Protocol,RFC2326,实时流传输协议,是TCP/IP协议体系中的一个应用层协议!协议主要规定定了一对多应用程序如何有效地通过IP网络传送多媒体数据。RTSP体系结位于RTP和RTCP之上(RTCP用于控制传输,RTP用于数据传输),使用TCP或UDP完成数据传输!
假设我们现在要向一个RTSP的sever发送请求获取数据,基本流程如下:

OPTIONS
C—>S
客户端向服务器端发送OPTIONS,请求可用的方法。
S—>C
服务器端回复客户端,消息中包含当前可用的方法。
DESCRIBE
C—>S
客户端向服务器请求媒体描述文件,一般通过rtsp开头的url来发起请求,格式为sdp。
S—>C
服务器回复客户端sdp文件,该文件告诉客户端服务器有哪些音视频流,有什么属性,如编解码器信息,帧率等。
SETUP
C—>S
客户端向服务器端发起建立连接请求,请求建立会话连接,准备开始接收音视频数据,请求信息描述了期望音视频数据包基于UDP还是TCP传输,指定了RTP,RTCP端口,以及是单播还是组播等信息!
S—>C
服务器端收到客户端请求后,根据客户端请求的端口号确定发送控制数据的端口以及音视频数据的端口!
PLAY
C—>S
客户端向服务端请求播放媒体。
S—>C
服务器回复客户端200 OK! 之后开始通过SETUP中指定的端口开始发送数据!
TEARDOWN
C---->S
结束播放的时候,客户端向服务器端发起结束请求
S—>C
服务端收到消息后,向客户端发送200 OK,之后断开连接
上述的流程基本涵盖了RTSP的流程,当然,RTSP除此之外,还有PAUSE,SCALE,GET_PARAMETER,SET_PARAMETER等参数。

RTSP消息分为两大类,一类是请求消息(request),一类是回应消息(ressponse)
请求消息的格式如下:

也就是说:
方法 URI RTSP版本 CR LF
消息头 CR LF CR LF
消息体 CR LF
1).请求消息的第一行的语法结构如下:
Request-Line = Method 空格 Request-URI 空格 RTSP-Version CRLF
其中方法包括OPIONS、DESCRIBE、SETUP、PLAY、TEARDOWN等,URI是接受方的地址,例如:rtsp://192.168.0.1/video1.3gp。
RTSP版本一般都是 RTSP/1.0。每行后面的CR LF表示回车换行,需要接受端有相应的解析,
2).在消息头中除了第一行的内容外,还有一些需求提供附加信息。其中有些是一定要的,后续我们会详细介绍经常用到的几个域的含义。
消息头 = Accept
| Accept-Encoding
| Accept-Language
| Authorization
| From
| If-Modified-Since
| Range
| Referer
| User-Agent
3).最后一个消息头需要有两个CR LF。消息体是可选的,有的Request消息并不带消息体。
如图中所示,该RTSP请求消息的方法为OPTIONS,请求的目标地址为rtsp://192.17.1.63:554,RTSP的版本为1.0;
接下来包含两种类型的消息,第一种为CSeq表示序列号,本次请求的序列号为1(服务器端回复此请求的数据包的序列号也是1);
第二种为User-Agent,表示用户代理,值为 “Lavf58.42.100”;
由于User-Agent为最后一条消息,其后要跟两组回车和换行!

用户代理为LibVLC/2.2.4,使用VLC播放器rtsp流的一个代理
响应报文的开始行是状态行,RTSP响应报文的结构如下图所示

也就是说:回应消息由RTSP版本+状态码+解释开头,之后跟一条或多条消息
RTSP版本 状态码 解释 CR LF
消息头 CR LF CR LF
消息体 CR LF
说明:
状态码:表示状态,同http的返回状态,如200,表示OK
解释:针对状态码的文本解释
同样:最后一条消息也是需要 跟两个回车和换行!


回复消息以Response标识,该消息中RTSP的版本号为1.0;
服务器回复的状态码为401;
针对状态码401的解释为Unauthorized(未授权);
包含两种类型的消息:
一是WWW-Authenticate:告诉请求端授权认证需要的信息;
二是Date:表示当前日期和时间!
sdp,英文全称Session Description Protocol,会话描述协议,对应RFC2327。我们在此介绍,是因为RTSP协议中使用sdp进行媒体信息的描述,不过,sdp的应用不止于此,语音通话SIP协议,监控安防GB28181国标, 当下比较火热的webRtc都用到了sdp,可谓应用广泛!
sdp的目的就是在媒体会话中,传递媒体流信息,允许会话描述的接收者去参与会话,定义了会话描述的统一格式!
OPTION是一个request消息,各个字段:
OPTIONS:标识请求命令的类型;
RTSP URI:请求的服务端的URI,以rtsp://开头的地址,一般为rtsp://ip:554(rtsp默认端口号);
RTSP VER:标识RTSP 版本号,一般常见RTSP/1.0;
CSeq:数据包序列号,由于OPTIONS一般而言为RTSP请求的第一条指令,一般而言,针对OPTIONS,该值为1;
User-Agent:用户代理;
回复消息的结构:
OPTIONS的回复遵循RTSP response消息的格式,第一行回复RTSP的版本,状态码,状态描述;然后是序列号,与OPTION请求中的序列号相同;之后是Public字段,用于描述服务器当前提供了哪些方法;最后是Date字段,表示日期。
最后放一个完整的OPTIONS请求的示例:
请求
OPTIONS rtsp://192.17.1.63:554 RTSP/1.0\r\n
CSeq: 1\r\n
User-Agent: Lavf58.42.100\r\
回复
RTSP/1.0 200 OK\r\n
CSeq: 1\r\n
Public: OPTIONS, DESCRIBE, PLAY, PAUSE, SETUP, TEARDOWN, SET_PARAMETER, GET_PARAMETER\r\n
Date: Fri, Apr 10 2020 19:07:19 GMT\r\n
上一篇我们介绍了RTSP的OPTION指令,客户端发起OPTION请求后,得到了RTSP服务器支持的指令。在此之后,客户端会继续向服务器发送DESCRIBE消息,来获取会话描述信息(sdp)。本篇我们来详细介绍一下DESCRIBE指令。
DESCRIBE的作用
向服务器请求会话描述信息(SDP)。
DESCRIBE的格式
1.请求
格式:
描述:
首先用DESCRIBE描述请求类型;然后在URI中请求的服务器端地址;RTSP_VER表示RTSP的版本号,在加入\r\n消息头结束;
消息体包含以下字段:
Accept:指明接收数据的格式,如application/sdp表示接收sdp信息,之后加入\r\n表示此条目结束;
CSeq:RTSP序列号,一般DESCRIBE包在RTSP请求过程中的序列号为2,之后加入\r\n表示此条目结束;
UserAgent : 指明用户代理,由于是最后一个条目,加入两组\r\n表示结束。
案例
第一次DESCRIBE请求:
DESCRIBE rtsp://192.17.1.63:554 RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf58.42.100
服务端回复的401消息:
RTSP/1.0 401 Unauthorized
CSeq: 2
WWW-Authenticate: Digest realm="IP Camera(23306)", nonce="a946c352dd3ad04cf9830d5e72ffb11e", stale="FALSE"
Date: Fri, Apr 10 2020 19:07:19 GMT
第二次DESCRIBE请求
DESCRIBE rtsp://192.17.1.63:554 RTSP/1.0
Accept: application/sdp
CSeq: 3
User-Agent: Lavf58.42.100
Authorization: Digest username="admin", realm="IP Camera(23306)", nonce="a946c352dd3ad04cf9830d5e72ffb11e", uri="rtsp://192.17.1.63:554", response="8f1987b6da1aeb3f3744e1307d850281"
验证OK消息
RTSP/1.0 200 OK
CSeq: 3
Content-Type: application/sdp
Content-Base: rtsp://192.17.1.63:554/
Content-Length: 712
v=0
o=- 1586545639954157 1586545639954157 IN IP4 192.17.1.63
s=Media Presentation
e=NONE
b=AS:5100
t=0 0
a=control:rtsp://192.17.1.63:554/
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:5000
a=recvonly
a=x-dimensions:1920,1080
a=control:rtsp://192.17.1.63:554/trackID=1
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z01AKI2NQDwBE/LgLcBAQFAAAD6AAAw1DoYACYFAABfXgu8uNDAATAoAAL68F3lwoA==,aO44gA==
m=audio 0 RTP/AVP 8
c=IN IP4 0.0.0.0
b=AS:50
a=recvonly
a=control:rtsp://192.17.1.63:554/trackID=2
a=rtpmap:8 PCMA/8000
a=Media_header:MEDIAINFO=494D4B48010300000400000111710110401F000000FA000000000000000000000000000000000000;
a=appversion:1.0
实际的案例:
request
SETUP rtsp://192.17.1.63:554/trackID=1 RTSP/1.0
Transport: RTP/AVP/UDP;unicast;client_port=26968-26969
CSeq: 4
User-Agent: Lavf58.42.100
Authorization: Digest username="admin", realm="IP Camera(23306)", nonce="a946c352dd3ad04cf9830d5e72ffb11e", uri="rtsp://192.17.1.63:554/trackID=1", response="e29ca030062df6022faa77fefde40b28"
Response
RTSP/1.0 200 OK
CSeq: 4
Session: 337474243;timeout=60
Transport: RTP/AVP/UDP;unicast;client_port=26968-26969;server_port=8284-8285;ssrc=4a7fb757;mode="play"
Date: Fri, Apr 10 2020 19:07:19 GMT
实例:
RTSP PLAY (requst)
PLAY rtsp://192.17.1.63:554/ RTSP/1.0\r\n
Range: npt=0.000-\r\n
CSeq: 6\r\n
User-Agent: Lavf58.42.100\r\n
Session: 337474243\r\n
Authorization: Digest username="admin", realm="IP Camera(23306)", nonce="a946c352dd3ad04cf9830d5e72ffb11e", uri="rtsp://192.17.1.63:554/", response="9ea6c2659d3bce8d129ca3549ecc7fbf"\r\n\r\n
RTSP PLAY (response)
RTSP/1.0 200 OK\r\n
CSeq: 6\r\n
Session: 337474243\r\n
RTP-Info: url=rtsp://192.17.1.63:554/trackID=1;seq=3658;rtptime=1710363406,url=rtsp://192.17.1.63:554/trackID=2;seq=6598;rtptime=4065225152\r\n
Date: Fri, Apr 10 2020 19:07:20 GMT\r\n\r\n
一个官方的例子:
PAUSE rtsp://example.com/fizzle/foo RTSP/1.0\r\n
CSeq:834\r\n
Session:12345678\r\n\r\n
PAUSE回复示例
RTSP/1.0 200 OK\r\n
CSeq:834\r\n
Session:12345678\r\n\r\n

该TREADOWN消息中,消息序列号为11,用户代理为LibVLC/2.2.4,这是我们使用VLC播放器rtsp流的一个代理,消息序列号为11, Session为之前SETUP请求后服务端Reply返回的session字段的值,用于表示此次会话连接!
发出去请求后,服务端同样也会回馈response的消息。
完整TEARDWON请求和回复的例子:
TEARDOWN请求
TEARDOWN rtsp://192.17.1.73:554/Streaming/Channels/101/?transportmode=unicast&profile=Profile_1 RTSP/1.0\r\n
CSeq: 10\r\n
Authorization: Digest username="admin", realm="bcad28138995", nonce="a1a5b9d3865180dccbaffb1cb2eb2a27", uri="rtsp://192.17.1.73:554/Streaming/Channels/101/", response="c5c005ef16638dfa326dcfc0c3f54aab"\r\n
User-Agent: LibVLC/3.0.11 (LIVE555 Streaming Media v2016.11.28)\r\n
Session: 1659421772\r\n\r\n
TEARDOWN的回复
RTSP/1.0 200 OK\r\n
CSeq: 10\r\n
Session: 1659421772\r\n
Date: Thu, Aug 27 2020 18:31:13 GMT\r\n\r\n
GetParameret用作向服务器获取参数,一般用于获取时间范围。当发送的请求中没有相关请求参数时,则用作保持RTSP连接!
从抓包文件中看并没有任何参数的信息,所以我们认为这是一个空的 RTSP请求,其作用是保持RTSP连接,类似于ping的作用,类似于RTMP协议中的ping request消息。如果有实际的参数请求,则在增加请求的参数对应的字段就可以了!
完整的GETPARAMETER的请求和回复的例子:
GET_PARAMETER请求
GET_PARAMETER rtsp://192.17.1.73:554/Streaming/Channels/101/?transportmode=unicast&profile=Profile_1 RTSP/1.0\r\n
CSeq: 7\r\n
Authorization: Digest username="admin", realm="bcad28138995", nonce="a1a5b9d3865180dccbaffb1cb2eb2a27", uri="rtsp://192.17.1.73:554/Streaming/Channels/101/", response="4764a1f2772821f5528ebbb2ad18c3f9"\r\n
User-Agent: LibVLC/3.0.11 (LIVE555 Streaming Media v2016.11.28)\r\n
Session: 1659421772\r\n\r\n
GET_PARAMETER回复
RTSP/1.0 200 OK\r\n
CSeq: 7\r\n
Date: Thu, Aug 27 2020 18:29:00 GMT\r\n
SET PARAMETER作用
SET_PARAMETER方法用于给URI指定的流地址设置参数。
当客户端想要确定为什么某一个特定的请求失败时,请求应该只包含一个参数。
如果请求中包含多个参数值,则服务器只有在所有的参数被成功设置的情况下,才会生效。
服务器允许某个参数被重复设置成相同的值,但不允许改变参数的值!
RTP概览
RTP是一种应用层协议,传输层协议可以是TCP或者UDP(UDP多一些)!
RTP数据包由两部分组成,一部分是RTP Heaeder,一部分是RTP body,RTP Header占用最少12个字节,最多72个字节;另一部分是RTP Payload,用来封装实际的数据负载,如封装h264编码的视频数据!下面我们来仔细看下RTP Header和RTP Body的组织形式!
通过Marker=1为最后一帧的 判断总处理的帧数是否等于Sequence number,据此判断是否丢帧
默认绿色是TCP报文,深蓝色是DNS,浅蓝是UDP,黑色标识出有问题的TCP报文——比如乱序报文。

Wireshark抓包的三次握手解析:
①客户端发起连接,先发送SYN报文,并发送序号为Seq=X=0;
②服务端收到客户端的连接请求后,发送SYN + ACK报文,并发送服务端发送的序号为Seq=Y=0,和确认序号ACK=X+1=1;
③客户端收到服务端的确认报文后,再次发送ACK报文给服务端,表示客户端能与服务端正常连接通信,并发送序号Seq=Z=1, 确认序号为ACK=Y+1=1;
最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
尝试通过SSL连接到ImgurAPI时出现错误。这是代码和错误:API_URI=URI.parse('https://api.imgur.com')API_PUBLIC_KEY='Client-ID--'ENDPOINTS={:image=>'/3/image',:gallery=>'/3/gallery'}#Public:Uploadanimage##args-Theimagepathfortheimagetoupload#defupload(image_path)http=Net::HTTP.new(API_URI.host)http.use_ssl=truehttp.verify
一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su
TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是
一、RIPV2协议简介 RIP(RoutingInformationProtocol)路由协议是一种相对古老,在小型以及同介质网络中得到了广泛应用的一种路由协议。RIP采用距离向量算法,是一种距离向量协议。RIP-1是有类别路由协议(ClassfulRoutingProtocol),它只支持以广播方式发布协议报文。RIP-1的协议报文无法携带掩码信息,它只能识别A、B、C类这样的自然网段的路由,因此RIP-1不支持非连续子网(DiscontiguousSubnet)。RIP-2是一种无类别路由协议(ClasslessRoutingProtocol),支持路由标记,在路由策略中可根据路由标记对
开门见山|拉取镜像dockerpullelasticsearch:7.16.1|配置存放的目录#存放配置文件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/config#存放数据的文件夹mkdir-p/opt/docker/elasticsearch/node-1/data#存放运行日志的文件夹mkdir-p/opt/docker/elasticsearch/node-1/log#存放IK分词插件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/plugins若你使用了moba,直接右键新建即可如上图所示依次类推创建
文章目录概念索引相关操作创建索引更新副本查看索引删除索引索引的打开与关闭收缩索引索引别名查询索引别名文档相关操作新建文档查询文档更新文档删除文档映射相关操作查询文档映射创建静态映射创建索引并添加映射概念es中有三个概念要清楚,分别为索引、映射和文档(不用死记硬背,大概有个印象就可以)索引可理解为MySQL数据库;映射可理解为MySQL的表结构;文档可理解为MySQL表中的每行数据静态映射和动态映射上面已经介绍了,映射可理解为MySQL的表结构,在MySQL中,向表中插入数据是需要先创建表结构的;但在es中不必这样,可以直接插入文档,es可以根据插入的文档(数据),动态的创建映射(表结构),这就
HTTP缓存是指浏览器或者代理服务器将已经请求过的资源保存到本地,以便下次请求时能够直接从缓存中获取资源,从而减少网络请求次数,提高网页的加载速度和用户体验。缓存分为强缓存和协商缓存两种模式。一.强缓存强缓存是指浏览器直接从本地缓存中获取资源,而不需要向web服务器发出网络请求。这是因为浏览器在第一次请求资源时,服务器会在响应头中添加相关缓存的响应头,以表明该资源的缓存策略。常见的强缓存响应头如下所述:Cache-ControlCache-Control响应头是用于控制强制缓存和协商缓存的缓存策略。该响应头中的指令如下:max-age:指定该资源在本地缓存的最长有效时间,以秒为单位。例如:Ca
如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1. 创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1. 创建SpringBoot项目 打开IDEA,选择NewProject创建项目。 填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。 选择springboot版本以及需要的包,此处只选择了springweb。 此处需特别注意,若你使用的是jdk1
前言上一篇我们简要讲述了粒子系统是什么,如何添加,以及基本模块的介绍,以及对于曲线和颜色编辑器的讲解。从本篇开始,我们将按照模块结构讲解下去,本篇主要讲粒子系统的主模块,该模块主要是控制粒子的初始状态和全局属性的,以下是关于该模块的介绍,请大家指正。目录前言本系列提要一、粒子系统主模块1.阅读前注意事项2.参考图3.参数讲解DurationLoopingPrewarmStartDelayStartLifetimeStartSpeed3DStartSizeStartSize3DStartRotationStartRotationFlipRotationStartColorGravityModif