RTSP-Server组件EasyRTSPServer客户端异常掉线导致部分通道阻塞问题解决方案

数据安
• 阅读 174

RTSP协议是一个流媒体协议,可以实现直播和点播形式的音频与视频流的播放。RTSP协议定义了多种服务器-客户端之间交互的接口,主要有OPTIONS,DESCRIBE,SETUP,PLAY,TEARDOWN,RECORD,ANNOUNCE。网络上已经有很多针对RTSP协议的文章,我这里不准备进行过多介绍。RTSP并不包括具体数据的传输,该功能一般由RTP与RTCP协议来实现,并可以通过TCP或UDP两种底层传输方式进行。

下图是典型的RTSP直播过程中服务端-客户端主要交互过程:

RTSP-Server组件EasyRTSPServer客户端异常掉线导致部分通道阻塞问题解决方案

EasyRTSPServer是一套稳定、高效、可靠、多平台支持的RTSP-Server组件, 接口调用非常简单成熟,今天为大家分享关于EasyRTSPServer客户端异常掉线导致部分通道阻塞的问题。

提出问题:

EasyRTSPServer在Linux环境下会因为客户端异常掉线后,偶现导致部分通道不能再被访问。

分析问题:

本来是分析服务端CLOSE_WAIT的问题,在调试的过程中, 却又发现了阻塞,认真分析了live555的事件调用流程后,发现只要从客户端收到数据,就会执行GenericMediaServer::ClientSession::noteLiveness(),在该函数中会删除上一次的超时事件,然后新建一个超时事件放入调度队列中,而客户端突然掉线,正常情况是会调用该超时任务, 在该任务中删除ClientSession, 在大量的客户端连接的情况下(128路)突然掉线, 就有几率会出现阻塞,从而导致没有调用到该超时事件,进而导致socket不能释放了。

销毁上一次的超时任务,创建一个新的超时任务

void GenericMediaServer::ClientSession::noteLiveness() {

  if (fOurServerMediaSession != NULL) fOurServerMediaSession->noteLiveness();

  if (fOurServer.fReclamationSeconds > 0) {
        pEnvironment->taskScheduler().rescheduleDelayedTask(fLivenessCheckTask,
                              fOurServer.fReclamationSeconds*1000000,
                              (TaskFunc*)livenessTimeoutTask, this);
}
}

超时任务实现如下

void GenericMediaServer::ClientSession::livenessTimeoutTask(ClientSession* clientSession) {
    delete clientSession;
}

加了N多的打印日志, 最终分析为epoll检测到了socket有事件,并且调用了相应的处理函数, 在该函数中,调用了recvfrom而导致阻塞… 恍然大悟, 赶紧搜一下SO_RCVTIMEO,果然,在live555所有代码中,没有搜到该关键字。

解决问题:

在创建socket后,设置接收数据超时时间即可。

#if defined(__WIN32__) || defined(_WIN32)
    DWORD msto = (DWORD)500;
    setsockopt(newSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&msto, sizeof(msto) );
    setsockopt(newSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&msto, sizeof(msto) );
#else
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 500*1000;
    setsockopt(newSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof tv);
    
    setsockopt(newSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv);
#endif
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
3年前
RTP、RTCP和RTSP协议基础
1RTSP概述1.1RTSP概念RTSP(RealTimeStreamProtocol)是一种基于文本的应用层协议,在语法及一些消息参数等方面,RTSP协议与HTTP协议类似。RTSP被用于建立的控制媒体流的传输,它为多媒体服务扮演“网络远程控制”的角色。RTSP本身并不用于传送媒体流数据。媒体数据的传
Wesley13 Wesley13
3年前
RTSP协议的状态机
本文翻译自rtsp协议的RFC2326官方文档附录ARTSPProtocolStateMachines节。状态是针对具体对象的,每一个对象由RTSPURL和会话ID唯一地标识。请求OPTIONS,ANNOUNCE,DESCRIBE,GET\_PARAMETER,SET\_PARAMETER不会影响客户端和服务器中对象的状态。一、客户端
GoCoding GoCoding
4年前
RTSP 流相关工具介绍
RTSP(RealTimeStreamingProtocol),实时流协议,是一种应用层协议,专为流媒体使用。本文将介绍GStreamer,VLC,FFmpeg这几个工具,如何发送、接收RTSP流。前提GStreamerGStreamer:https://gstreamer.freedesktop.org/GStre
liuzhen007 liuzhen007
4年前
Golang根据URL判断媒体协议
目录问题解决问题如何根据一个流媒体地址URL判断对应的流媒体协议,比如RTMP、RTSP协议等。解决这里提供一个方法,可以直接拿来用。golangfuncgetProtocol(urlstring)(string,error){ifurl""{index:strings.Index(url,":")
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0