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

  • 相关阅读:
    acme.sh 申请let's encrypt证书
    Excel 函数
    mysql索引失效的情况
    mysql之EXPLAIN优化分析
    mysql索引
    mysql视图
    mysql数据类型
    mysql约束
    mysql库和表的管理
    mysql的DML语言(增删改)
  • 原文地址:https://www.cnblogs.com/babosa/p/9217726.html
Copyright © 2011-2022 走看看