多平台支持的RTSP-Server组件EasyRTSPServer在rtp over udp客户端没有发送teardown关闭导致Server没有即时关闭流怎么办?

RTSP(Real Time Streaming Protocol)是由Real Network和Netscape共同提出的如何有效地在IP网络上传输流媒体数据的应用层协议。RTSP对流媒体提供了诸如暂停,快进等控制,而它本身并不传输数据,RTSP的作用相当于流媒体服务器的远程控制。服务器端可以自行选择使用TCP或UDP来传送串流内容,它的语法和运作跟HTTP 1.1类似,但并不特别强调时间同步,所以比较能容忍网络延迟。而且允许同时多个串流需求控制(Multicast),除了可以降低服务器端的网络用量,还可以支持多方视频会议(Video onference)。EasyRTSPServer应运而生。

EasyRTSPServer在rtp over udp客户端没有发送teardown关闭导致Server没有即时关闭流

提出问题:

在rtp over udp模式下, rtsp客户端没有发送teardown而直接断开连接时需要等待65秒才回调关闭的问题

分析问题:

在RTSPClientConnection中没有保存相应的session值, 所以在RTSPClientConnection断开时, 并没有删除相应的RTSPClientSession;

解决问题:

	在RTSPClientConnection的声明中,增加以下定义;
	char fClientSessionIdStr[16];	//for rtp over udp
	
	GenericMediaServer.hh  增加createNewClientSessionWithId的参数char *pSessionIdStr
	ClientSession* createNewClientSessionWithId(UsageEnvironment	*pEnv, char *pSessionIdStr);
	
	GenericMediaServer::ClientSession* GenericMediaServer::createNewClientSessionWithId(UsageEnvironment	*_pEnv, char *pSessionIdStr) {
	  u_int32_t sessionId;
	  char sessionIdStr[16] = {0};

	  // Choose a random (unused) 32-bit integer for the session id
	  // (it will be encoded as a 8-digit hex number).  (We avoid choosing session id 0,
	  // because that has a special use by some servers.)
	  do {
	    sessionId = (u_int32_t)our_random32();
	    snprintf(sessionIdStr, sizeof sessionIdStr, "%08X", sessionId);
	  } while (sessionId == 0 || lookupClientSession(sessionIdStr) != NULL);

	  ClientSession* clientSession = createNewClientSession(sessionId, _pEnv);
	  if (clientSession != NULL) fClientSessions->Add(sessionIdStr, clientSession);

	  if (NULL != pSessionIdStr)	strcpy(pSessionIdStr, sessionIdStr);		//此处返回生成的sessionId, 后续要根据该值找到对应的ClientSession

	  return clientSession;
	}		
	
	
	
	void RTSPServer::RTSPClientConnection::handleRequestBytes(int newBytesRead, UsageEnvironment *pEnv) {

		//找到以下代码		
	  if (authenticationOK("SETUP", urlTotalSuffix, (char const*)fRequestBuffer)) {
		  memset(fClientSessionIdStr, 0x00, sizeof(fClientSessionIdStr));
	    clientSession
	      = (RTSPServer::RTSPClientSession*)fOurRTSPServer.createNewClientSessionWithId(pEnv, fClientSessionIdStr);		//此处记录ClientSession的sessionId
	  }		
	
	}

此时,在RTSPClientConnection中已经保存了对应的SessionId, 在客户端断开连接时, 可以根据该SessionId, 找到相应的ClientSession, 然后删除;

	void RTSPServer::stopTCPStreamingOnSocket(UsageEnvironment *pEnv, int socketNum, int *clientTrackNum, char *clientSessionIdStr){
	  // Close any stream that is streaming over "socketNum" (using RTP/RTCP-over-TCP streaming):

		RTSPClientSession	*pClientSession = NULL;

		LockClientConnection();
		do
		{
		  streamingOverTCPRecord* sotcp
			= (streamingOverTCPRecord*)fTCPStreamingDatabase->Lookup((char const*)socketNum);
		  if (sotcp != NULL) {		//rtp over tcp
			do {
			  RTSPClientSession* clientSession
			= (RTSPServer::RTSPClientSession*)lookupClientSession(sotcp->fSessionId);
			  if (clientSession != NULL) {
				  //clientSession->SetAssignSink(assignSink);
			clientSession->deleteStreamByTrack(pEnv, sotcp->fTrackNum, False, clientTrackNum);
			  }

			  streamingOverTCPRecord* sotcpNext = sotcp->fNext;
			  sotcp->fNext = NULL;
			  delete sotcp;
			  sotcp = sotcpNext;
			} while (sotcp != NULL);
			fTCPStreamingDatabase->Remove((char const*)socketNum);
		  }
		  else if ( (clientTrackNum) && (*clientTrackNum==0))		//rtp over udp
		  {
			  pClientSession = (RTSPServer::RTSPClientSession*)lookupClientSession(clientSessionIdStr);
		  }
		}while (0);

		UnlockClientConnection();

		if (pClientSession != NULL) 		//pClientSession不为空, 说明为rtp over udp
		{
			delete pClientSession;
		}

	}
posted on 2019-10-15 17:10  TSINGSEE  阅读(286)  评论(0编辑  收藏  举报