zoukankan      html  css  js  c++  java
  • rtmp直播拉流客户端EasyRTMPClient TCP窗口大小设计方法

    EasyRTMPClient 简介

    EasyRTMPClient是EasyDarwin流媒体团队开发、提供的一套非常稳定、易用、支持重连接的RTMPClient工具,以SDK形式提供,接口调用非常简单。该EasyRTMPClient库未使用或参考现有的任何RTMP库,完全由EasyDarwin团队自主实现,因此,EasyRTMPClient更易于维护,稳定性、可扩展性得以提升,同时,本RTMP库全平台支持(包括windows/linux 32&64,ARM各平台,android, ios)!

    相关连接

    EasyRTMPClient调用示例地址:https://github.com/EasyDSS/EasyRTMPClient

    由EasyDarwin团队推出的 RTMP协议教程:初级部分 进阶部分 高级部分

    谈谈RTMP窗口大小

    RTMP窗口大小基本概念

    RTMP消息包一共分成三种类型。一类是命令(通知)消息,一类是音频消息,一类是视频消息。而窗口大小则属于第一种消息,即命令消息。窗口大小的本意是让对端了解与本端的通信状况,用以控制媒体传输流量的一种方案。通常,我们从RTMP服务器中进行拉取RTMP流到本地时,在协商的过程当中,会发送0x05,0x06消息包,即带宽值通知,通常设为2.5M。在实际的拉流过程中,我们通常隔一段时间就得向服务器报告,我们已经从服务中收到了多少数据量,此种报告,就是开篇所提到的窗口大小,即ack size确认。我在实际开发的过程当中,通常,当接收的数据量接近于3倍带宽值(2.5M*3)时,向服务器报告一下目前已接收了多少数据。经测试,针对于Flash Media Server(FMS)对该消息是比较敏感的(其它RTMP服务器,各方实现不同,对该窗口大小的确认或许没有如此敏感)。如果客户端未能及时向FMS回馈该数据,即使在正常的拉收数据流的过程当中,FMS也会断开与客户的连接。

    由RTMP窗口大小引发的问题

    上述,基本对RTMP窗口大小做了一个介绍。根据RTMP协议标准来看,RTMP窗口大小是通过0x03类型来标识的,其负载通常是四个字节,用大端序来表示当前窗口大小,即当前已接收的数据总量。前面,我们说过,FMS对窗口大小这条消息是十分敏感的,除了按上述方法,及时向FMS反馈0x03消息包(窗口大小确认)外,仍须注意另一个问题,即4字节溢出的情况。我们知道,4字节无符号,大概能表示4.29G左右的数据量,当从RTMP服务器所接收的数据量即将达到4.29G时,应及时的向RTMP服务器进行一次窗口大小的置零反馈。该bug是经过大量时间分析而得来,据后来查验,librtmp库也同样存在该bug(该Bug于2013/2014年左右遇到并分析处理),由于我没用librtmp库,因此,暂不能确认当前版本是否有修正该bug(应该没有修正 ^_^)。

    EasyRTMPClient 中的处理

    在实际的开发过程当中,当我们接收的数据量接近于4.29G时,我们及时将该值提前置0,反馈给FMS服务器即可。如果过早的置0,或直接等待其溢出,FMS同样会立即断开RTMP客户端。下面贴出EasyRTMPClient对上述Bug的处理代码:

    int SendWindowAcknowledgementSize( MSRtmpSession * msrs )
    {
        int ret = 0;
        MRPKT * pkt = NULL;
        MPARASITICAL_BUFS * bufs = NULL;
    
        pkt = allocRMPkt();
        if ( !pkt )
        {
            return -1;
        }
    
        writeMessageHdr( 0x02, 0, 0, 0x03, -1, pkt );
    
        bufs = msrs->msr->hdr.alloc( msrs->msr->hdr.hdr );
        *( ( unsigned int * )bufs->buf ) = htonl( msrs->msr->info.recvInfo.bytes );
        bufs->len = sizeof( unsigned int );
        msrs->msr->info.ackSize = msrs->msr->info.recvInfo.bytes;                          // reference for next send ack size
    
        fillPayload( bufs, pkt, msrs->msr ); 
        commitMRPkt( pkt, msrs->msr );
    
        ret = MRSendChunks( msrs, &pkt, -1 );
    
        if ( msrs->msr->info.recvInfo.bytes + msrs->msr->info.clientBW * 3 > 4294967295 )  // stream bytes > 4.2G, ack clean.
        {
            msrs->msr->info.recvInfo.bytes = 0;                                            // Improve by Inpilen.
            msrs->msr->info.ackSize = 0;
        }
    
        return ret;
    }
    

    获取更多信息

    邮件:support@easydarwin.org

    WEB:www.EasyDarwin.org

    EasyRTMPClient交流群:544917793

    Copyright © EasyDarwin.org 2012-2017

    EasyDarwin

  • 相关阅读:
    安装lnmp 时如何修改数据库数据存储地址及默认访问地址
    ubuntu 设置root用户密码并实现root用户登录
    解决ubuntu 远程连接问题
    linux 搭建FTP服务器
    PHP 根据ip获取对应的实际地址
    如何发布自己的composer包
    使用composer安装composer包报Your requirements could not be resolved to an installable set of packages
    laravel 框架配置404等异常页面
    使用Xshell登录linux服务器报WARNING! The remote SSH server rejected X11 forwarding request
    IoTSharp 已支持国产松果时序数据库PinusDB
  • 原文地址:https://www.cnblogs.com/babosa/p/9217726.html
Copyright © 2011-2022 走看看