live555 服务端推流自动断开

10 篇文章 2 订阅

使用live555作为服务端推流,基于udp传输时比较正常,但切换tcp 经常一段时间后自己断开。
原因一: 服务端故意为之。
rtsp 协议的传输使用tcp,在RTSPserver.hh, RTSPServer的构造函数中有:

class RTSPServer: public GenericMediaServer {
public:
  static RTSPServer* createNew(UsageEnvironment& env, Port ourPort = 554,
			       UserAuthenticationDatabase* authDatabase = NULL,
			       unsigned reclamationSeconds = 65);
      // If ourPort.num() == 0, we'll choose the port number
      // Note: The caller is responsible for reclaiming "authDatabase"
      // If "reclamationSeconds" > 0, then the "RTSPClientSession" state for
      //     each client will get reclaimed (and the corresponding RTP stream(s)
      //     torn down) if no RTSP commands - or RTCP "RR" packets - from the
      //     client are received in at least "reclamationSeconds" seconds.
......
}

第四个参数默认值是65, 表示如果 rtsp的socket 持续65s没有输入发生,就会关掉这个 tcp socket。对应代码在GenericMediaServer.cpp GenericMediaServer::ClientSession::noteLiveness(), 以节约资源。
同样的操作,在vlc作为rtsp服务端的时候,也有这样的机制,对应的代码在 /modules/stream_out/rtsp.c RtspSetup()

 if (rtsp->timeout > 0)
        if (vlc_timer_create(&rtsp->timer, RtspTimeOut, rtsp))


对于使用UDP传输的 rtp,传输数据是单独的udp socket,而使用rtp-over-tcp传输的时候,rtsp、rtp、rtcp、都是复用这一个tcp socket,所以这里关掉这个唯一的 tcp socket ,整个流传输都将关闭。
解决: 1.0 客户端按照一定频率发送 rtcp,类似保活功能
            2.0 出于调试的目的,最简单的方法,就是关掉服务端这个超时关闭的功能。

 // 第四个参数 0 ,表示一直保持连接,否则默认持续 65s 都没有rtsp的通信,就关掉rtsp socket.
 RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554, authDB,0);

原因二:服务端传输 rtp,写socket错误,主动关闭。
对于比较大的视频码流,或者网络很差的情况下,出现概率比较高。
对应代码在 RTPInterface.cpp 

Boolean RTPInterface::sendDataOverTCP(int socketNum, u_int8_t const* data, unsigned dataSize, Boolean forceSendToSucceed) {

//第一次发送
int sendResult = send(socketNum, (char const*)data, dataSize, 0/*flags*/);
  if (sendResult < (int)dataSize) {
    // The TCP send() failed - at least partially.

    unsigned numBytesSentSoFar = sendResult < 0 ? 0 : (unsigned)sendResult;
    if (numBytesSentSoFar > 0 || (forceSendToSucceed && envir().getErrno() == EAGAIN)) {

//第一次发送不成功
      // The OS's TCP send buffer has filled up (because the stream's bitrate has exceeded
      // the capacity of the TCP connection!).
      // Force this data write to succeed, by blocking if necessary until it does:
      unsigned numBytesRemainingToSend = dataSize - numBytesSentSoFar;
#ifdef DEBUG_SEND
      fprintf(stderr, "sendDataOverTCP: resending %d-byte send /%d (blocking)\n", numBytesRemainingToSend,dataSize); fflush(stderr);
#endif
//采用阻塞方式,超时时间默认 500ms,重发
      makeSocketBlocking(socketNum, RTPINTERFACE_BLOCKING_WRITE_TIMEOUT_MS);
      sendResult = send(socketNum, (char const*)(&data[numBytesSentSoFar]), numBytesRemainingToSend, 0/*flags*/);
      if ((unsigned)sendResult != numBytesRemainingToSend) {
	// The blocking "send()" failed, or timed out.  In either case, we assume that the
	// TCP connection has failed (or is 'hanging' indefinitely), and we stop using it
	// (for both RTP and RTP).
	// (If we kept using the socket here, the RTP or RTCP packet write would be in an
	//  incomplete, inconsistent state.)
#ifdef DEBUG_SEND
	fprintf(stderr, "sendDataOverTCP: blocking send() failed (delivering %d bytes out of %d); closing socket %d\n", sendResult, numBytesRemainingToSend, socketNum); fflush(stderr);
#endif


//重发失败,关闭socket
	removeStreamSocket(socketNum, 0xFF);
	return False;
	
      }
      makeSocketNonBlocking(socketNum);

      return True;
    } else if (sendResult < 0 && envir().getErrno() != EAGAIN) {
      // Because the "send()" call failed, assume that the socket is now unusable, so stop
      // using it (for both RTP and RTCP):
      removeStreamSocket(socketNum, 0xFF);
    }
}

视频帧比较大的时候,经常出现重发,然后重发又失败,导致主动关闭了socket. 在编译的时候加上 宏定义 -DDEBUG_SEND,可以看到这里的输出。
解决: 源码里面直接把这个 removeStreamSocket() 注释掉吧,虽然不建议直接修改源码。
 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值