#PS:要转载请注明出处,本人版权所有

#PS:这个只是 《 我自己 》理解,如果和你的

#原则相冲突,请谅解,勿喷

背景

参考前置文章:《一个简单的RTMP服务器实现 — RTMP与H264》
https://blog.csdn.net/u011728480/article/details/85770696

前置知识

《一个简单的RTMP服务器实现 — RTMP与H264》:https://blog.csdn.net/u011728480/article/details/85770696
《一个简单的RTMP服务器实现 — RTMP与FLV》:https://blog.csdn.net/u011728480/article/details/85780974

RTMP简介

RTMP是Real Time Messaging Protocol的简写。RTMP是应用层协议,其是基于TCP实现的。

网上有许多介绍RTMP基础知识的地方,本文不重复介绍。但是如果有人对以下概念不熟悉的,建议去随意找一篇翻译《rtmp_specification_1.0.pdf》的文章即可。

阅读本文需要找一篇RTMP的详细知识总结,一起配合阅读。

RTMP基本知识要点

Chunk 、ChunkStream和ChunkStreamID

Chunk是RTMP的一种应用层分包结构。

ChunkStream是一种逻辑通道,代表的是RTMP Message分包为Chunk之后的传输的一种数据流。可从服务器到客户端,反之亦然。

ChunkStreamID是描述ChunkStream的一个ID,消息拆包为Chunk后,可根据此ID的标识来组合Message。其取值范围为3~65599(2^16 -1 + 2 ^6 -1)。0代表2byte形式ChunkbasicHeader,1代表3byte形式ChunkbasicHeader。2代表是控制消息和命令的流。

下图为chunkbasicheader格式图:

下图为chunk格式图:

Message、MessageStream和MessageStreamID

Message是RTMP协议的基本数据结构。绝大部分RTMP协议的数据发送都必须按照此结构来封装。

MessageStream也是一种逻辑通道,它描述的是一种消息流。根据抓包结果显示,基本的消息通信为一种消息流,音视频消息通信为另外一种流。这种逻辑流在RTMP播放过程中一定要注意。

MessageStreamID是一种表示MessageStream的ID。

Message有多种结构,由chunkbasicheader中fmt字段决定,有如下四种格式:
type0

type1

type2

type3
没有头结构。

Message ~ Control Message

控制消息是一些设置属性的消息。他们的MessageTypeId是1-7.

  1. MessageTypeId==1,设置Chunk分包大小,默认为128bytes

  2. MessageTypeId==2,终止消息,如果一个消息正在被等待接收完毕(Chunk分包没有接收完毕),那么本消息用于放弃这个消息的等待。

  3. MessageTypeId==3,确认消息。本消息用于发送本客户端接收到了多少数据。

  4. MessageTypeId==4,用户控制报文信息。具体用户控制报文看后文

用户控制报文协议中Stream Begin是实现RTMP的播放的重要的一个报文。详情参考RTMP官方文档,及其他参考资料。

  1. MessageTypeId==5,发送窗口确认大小信息。用于设置窗口大小,达到这个值后,回复确认信息。

  2. MessageTypeId==6,设置对端带宽信息。如果,携带的确认窗口信息大小和之前不一致,要回应一个确认窗口信息大小。反之,不回应。

  3. MessageTypeId==7 ,保留。

Message ~ Command Message

MessageTypeId==17或者20. 17对应的格式是AMF3,20对应的格式是AMF0.
connect, createStream, publish, play, pause等命令是非常重要的。特别注意其中的事物ID,这个ID是关键。

Message ~ Data message

MessageTypeId==18或者15. 18对应的格式是AMF0。15对应的格式是AMF3.
Metadata的发送,就要靠此类型的消息。

Message ~ Shared object message

MessageTypeId==19或者16,19对应格式是AMF0,16对应的格式是AMF3.

Message ~ Audio message

MessageTypeId==8 音频数据

Message ~ Video message

MessageTypeId==9 视频数据

Message ~ Aggregate message

MessageTypeId==22 聚集消息数据

NetConnection相关命令

NetConnection相关的命令是用于处理RTMP连接方面的问题,当使用命令createstream后,就会创建成功一个流了,就会切换到NetStream相关命令下工作。

本文的服务器用了的命令为connect、createstream等等。

具体用法可看下文抓包分析,特别是这些命令的的回应,是本文的重点。

NetStream相关命令

本文的服务器用了命令为play、pause等等。
具体用法可看下文抓包分析,特别是这些命令的的回应,是本文的重点。

AMF0和AMF3格式

这种格式是用来序列化相关数据的。具体参考其他文章。

RTMP 通信流程分析(理论和抓包结合)

RTMP 简单握手(此种握手为造成一个坑爹的问题,具体看文末注意事项。)

c0和s0结构:

c0和s0实际抓包:

C1和S1结构:

zero字段必须为0.
random区域长度为1528bytes的随机数。

C1和S1实际抓包:

从图中可以看出,我服务器回应的随机字节基本都是0。

C2和S2实际抓包:

图中可以看出,S2C1。同理C2S1。

简单握手时序图:

实际过程中,C0和C1一起发送,服务器一起回应S0,S1,S2。当握手完毕后,就会进入下一阶段。

RTMP 连接及响应

首先给出连接及响应时序图:

Command Message 之 connect

从这里可以看到,connect命令携带了rtmp流地址的属性以及相关的版本。关于这个命令的重点其实是其事物ID的值是1。

作为connect的回应,这里一般来说有如下几个基本消息需要发送:
确认窗口大小信息
设置带宽信息
设置Chunk分包大小

最终,我们需要对connect命令进行回应,如果不回应或者回应错误,将不会走到下一步。

_result命令:
这里的一个重点是事物ID必须为1,表示对connect的回应。
其次,携带的object必须包含connect的状态回应属性,如:NetConnection.Connect.Success和Connection succeeded.等等

当客户端收到connect 的回应后,客户端发送createstream命令,服务端收到createstream命令后,发送createstream响应命令。

注意画框部分的事物ID,同时也注意回应命令中,数字为1的流ID,这个值代表的是对于本次连接,MessageStreamID必须为此值。对于本连接来说,后续所有需要发送MessageStreamID的地方必须填写此值,才能够完成相关通信。

RTMP 播放及响应命令

播放时序图:

当创建流成功后,客户端会发送一个play命令:

这里需要注意的是事物ID为0,且包含要播放那个视频流的属性。这里的test就是这个地址里面的rtmp://xxx.xxx.xxx.xxx/live/test

这个时候服务器会设置相应的属性:如设置chunk大小等等。同时服务器会回应用户控制消息streambegin。

最后服务器会回应play命令:

这个时候,其实就是可以发送媒体数据了,但是根据抓包结果显示,还需要这个数据:

RTMP传输音视频

在传输音视频之前,必须先传输onMetaData(参考flv一文)数据。

然后可以传输音视频数据了,
但是传输普通的音视频数据之前,必须传输相关的配置数据。对于h264视频来说,就是flv一文中的AVCDecoderConfigurationRecord 的videotag数据。然年即可传输普通的音视频数据。

注意:在创建成功一个流之后,发送的媒体数据中的MessageStreamID必须为上文createstream 返回的值。

注意

如果严格按照上文实现,就可以用vlc或者plotplayer等等播放对应的RTMP流。但是,Flash网页播放器一定不能够播放(具体表现为所有都工作正常,只是页面没有画面,像没有接收到数据一样)。原因是简单握手导致的。

总结:
1 根据官方文档实现相关功能后,如果没有达到预期效果,别急慢慢排查。至少我是这样的,别把思路搞混了就行了。
2 还有一个教训就是:相信自己,要敢于怀疑别人的资料是错的。

#PS:请尊重原创,不喜勿喷

#PS:要转载请注明出处,本人版权所有.

有问题请留言,看到后我会第一时间回复

一个简单的RTMP服务器实现 --- RTMP实现要点相关推荐

  1. 【Android RTMP】RTMPDump 推流过程 ( 独立线程推流 | 创建推流器 | 初始化操作 | 设置推流地址 | 启用写出 | 连接 RTMP 服务器 | 发送 RTMP 数据包 )

    文章目录 安卓直播推流专栏博客总结 一. Java 层传入的 RTMP 推流地址处理 二. RTMPDump 推流线程 三. 创建 RTMP 对象 四. 初始化 RTMP 对象 五. 设置 RTMP ...

  2. Linux网络管理之四:创建一个简单的vsftpd服务器

    VSFTPD主要配置文件如下:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" ...

  3. ipad php mysql_如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1

    原文:http://www.raywenderlich.com/2941/how-to-write-a-simple-phpmysql-web-service-for-an-ios-app 作为一个i ...

  4. 在Linux上搭建 一个简单的vsftpd服务器

    主要配置文件如下: /etc/vsftpd/vsftpd.conf 主配置文件 /etc/vsftpd.ftpusers 阻止用户访问FTP服务器的用户名称清单 /etc/vsftpd.userlis ...

  5. 我的Go语言学习之旅八:创建一个简单的WEB服务器

    因为一直在做WEB程序,所以更关注WEB界的发展,这里就用GO做了一个简单的WEB服务器,直接看例子吧 package main import ( "fmt" "net/ ...

  6. [C# 网络编程系列]专题十二:实现一个简单的FTP服务器

    引言: 休息一个国庆节后好久没有更新文章了,主要是刚开始休息完心态还没有调整过来的, 现在差不多进入状态了, 所以继续和大家分享下网络编程的知识,在本专题中将和大家分享如何自己实现一个简单的FTP服务 ...

  7. 3-4:一个简单的HTTP服务器

    文章目录 HTTP服务器 HTTP服务器 我们使用浏览器请求某一个网页时,浏览器会向相应的服务器发送请求,服务器得到请求后会将报文传送回来,然后浏览器解析,就形成了我们所看见到的网页 这里我们可以写一 ...

  8. ios php mysql实例_如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1

    原文:http://www.raywenderlich.com/2941/how-to-write-a-simple-phpmysql-web-service-for-an-ios-app 作为一个i ...

  9. http服务器响应格式,熟悉Http协议的请求和响应格式,编写一个简单的Http服务器。 基本要求:1 正确解...

    熟悉Http协议的请求和响应格式,编写一个简单的Http服务器. 基本要求: 1 正确解 2016-08-23 0 0 0 暂无评分 其他 1 积分下载 如何获取积分? 熟悉Http协议的请求和响应格 ...

最新文章

  1. 深度学习中的线代基础
  2. 简单几段python代码_如何用python跑一段鸿蒙最简单代码?
  3. 如何写一份优秀的Java程序员简历?
  4. 关于GPU-driver for linux的资料
  5. OpenCv学习笔记(二)—cv Mat学习
  6. matlab 价格统计,matlab中的金融数据统计
  7. Linux系统下MySQL导出数据库和导入数据库的命令
  8. [转帖]win10 .Net Runtime Optimization Service占用大量CPU资源解决方法
  9. mysql 集中join的区别
  10. JavaScript的初步探索(JS的入坑笔录)
  11. 物联网的体系结构分为_初学物联网信息安全、3
  12. NoSQL数据库——Hbase
  13. IBM ThinkPad SL400 XP驱动
  14. 电商管理系统的作用?好用的电商管理系统有哪些特点?
  15. Direct3D9初始化-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(6)
  16. 如何用css绘制一个三角形
  17. 阿里云负载均衡的配置和使用场景
  18. 记录安卓,IOS安装kali的办法
  19. 操作:FTP服务器的搭建
  20. zan php demo,ajax+php+mysql实现无刷新点赞功能

热门文章

  1. 华为Linux送的u盘,微软无奈,断供系统没用,华为和荣耀给用户赠送带Windows的U盘...
  2. linux+ping网络脚本,使用ping命令检测整个网段IP的网络状态的shell脚本(图文)
  3. 协程为什么比多线程快?在什么情况下更快?
  4. 从此,慕尼黑电子展不止有上海,还有深圳!
  5. 修改ip地址指定域名
  6. 234、各品牌路由器登录网址大全 路由器默认用户名/密码
  7. 5G智能专网是什么?有什么用?怎么部署?
  8. MLaPP Chapter 6 Frequentist statistics 频率学派统计学
  9. 父亲节:再见,总有一天
  10. html中以菱形为边框,使用 border 画流程图中的决策框 (菱形框) 的代码教程