live555做流媒体服务器时解决rtp over udp模式下, 客户端没有发送teardown时直接关闭导致RTSPServer端没有即时关闭流的问题解决方法

在我们使用live555作为RTSP服务器时,客户端在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;
			}

		}

#!/usr/bin/env bash set -e # ----------------------------------------------------------------------------- # Usage and command-line argument parsing # ----------------------------------------------------------------------------- function usage() { echo "Usage: $0 [--disable-webserver] [--disable-taskexecutor] [--consumer-no-beg=<num>] [--consumer-no-end=<num>] [--workers=<num>] [--host-id=<string>]" echo echo " --disable-webserver Disables the web server (nginx + ragflow_server)." echo " --disable-taskexecutor Disables task executor workers." echo " --enable-mcpserver Enables the MCP server." echo " --consumer-no-beg=<num> Start range for consumers (if using range-based)." echo " --consumer-no-end=<num> End range for consumers (if using range-based)." echo " --workers=<num> Number of task executors to run (if range is not used)." echo " --host-id=<string> Unique ID for the host (defaults to \`hostname\`)." echo echo "Examples:" echo " $0 --disable-taskexecutor" echo " $0 --disable-webserver --consumer-no-beg=0 --consumer-no-end=5" echo " $0 --disable-webserver --workers=2 --host-id=myhost123" echo " $0 --enable-mcpserver" exit 1 } ENABLE_WEBSERVER=1 # Default to enable web server ENABLE_TASKEXECUTOR=1 # Default to enable task executor ENABLE_MCP_SERVER=0 CONSUMER_NO_BEG=0 CONSUMER_NO_END=0 WORKERS=1 MCP_HOST="127.0.0.1" MCP_PORT=9382 MCP_BASE_URL="http://127.0.0.1:9380" MCP_SCRIPT_PATH="/ragflow/mcp/server/server.py" MCP_MODE="self-host" MCP_HOST_API_KEY="" # ----------------------------------------------------------------------------- # Host ID logic: # 1. By default, use the system hostname if length <= 32 # 2. Otherwise, use the full MD5 hash of the hostname (32 hex chars) # ----------------------------------------------------------------------------- CURRENT_HOSTNAME="$(hostname)" if [ ${#CURRENT_HOSTNAME} -le 32 ]; then DEFAULT_HOST_ID="$CURRENT_HOSTNAME" else DEFAULT_HOST_ID="$(echo -n "$CURRENT_HOSTNAME" | md5sum | cut -d ' ' -f 1)" fi HOST_ID="$DEFAULT_HOST_ID" # Parse arguments for arg in "$@"; do case $arg in --disable-webserver) ENABLE_WEBSERVER=0 shift ;; --disable-taskexecutor) ENABLE_TASKEXECUTOR=0 shift ;; --enable-mcpserver) ENABLE_MCP_SERVER=1 shift ;; --mcp-host=*) MCP_HOST="${arg#*=}" shift ;; --mcp-port=*) MCP_PORT="${arg#*=}" shift ;; --mcp-base-url=*) MCP_BASE_URL="${arg#*=}" shift ;; --mcp-mode=*) MCP_MODE="${arg#*=}" shift ;; --mcp-host-api-key=*) MCP_HOST_API_KEY="${arg#*=}" shift ;; --mcp-script-path=*) MCP_SCRIPT_PATH="${arg#*=}" shift ;; --consumer-no-beg=*) CONSUMER_NO_BEG="${arg#*=}" shift ;; --consumer-no-end=*) CONSUMER_NO_END="${arg#*=}" shift ;; --workers=*) WORKERS="${arg#*=}" shift ;; --host-id=*) HOST_ID="${arg#*=}" shift ;; *) usage ;; esac done # ----------------------------------------------------------------------------- # Replace env variables in the service_conf.yaml file # ----------------------------------------------------------------------------- CONF_DIR="/Users/congcong/programfile/ragflow/conf" TEMPLATE_FILE="${CONF_DIR}/service_conf.yaml.template" CONF_FILE="${CONF_DIR}/service_conf.yaml" rm -f "${CONF_FILE}" while IFS= read -r line || [[ -n "$line" ]]; do eval "echo \"$line\"" >> "${CONF_FILE}" done < "${TEMPLATE_FILE}" export LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu/" PY=python3 # ----------------------------------------------------------------------------- # Function(s) # ----------------------------------------------------------------------------- function task_exe() { local consumer_id="$1" local host_id="$2" JEMALLOC_PATH="$(pkg-config --variable=libdir jemalloc)/libjemalloc.so" while true; do LD_PRELOAD="$JEMALLOC_PATH" \ "$PY" rag/svr/task_executor.py "${host_id}_${consumer_id}" done } function start_mcp_server() { echo "Starting MCP Server on ${MCP_HOST}:${MCP_PORT} with base URL ${MCP_BASE_URL}..." "$PY" "${MCP_SCRIPT_PATH}" \ --host="${MCP_HOST}" \ --port="${MCP_PORT}" \ --base_url="${MCP_BASE_URL}" \ --mode="${MCP_MODE}" \ --api_key="${MCP_HOST_API_KEY}" & } # ----------------------------------------------------------------------------- # Start components based on flags # ----------------------------------------------------------------------------- if [[ "${ENABLE_WEBSERVER}" -eq 1 ]]; then echo "Starting nginx..." #/usr/sbin/nginx echo "Starting ragflow_server..." while true; do "$PY" /Users/congcong/programfile/ragflow/api/ragflow_server.py done & fi if [[ "${ENABLE_MCP_SERVER}" -eq 1 ]]; then start_mcp_server fi if [[ "${ENABLE_TASKEXECUTOR}" -eq 1 ]]; then if [[ "${CONSUMER_NO_END}" -gt "${CONSUMER_NO_BEG}" ]]; then echo "Starting task executors on host '${HOST_ID}' for IDs in [${CONSUMER_NO_BEG}, ${CONSUMER_NO_END})..." for (( i=CONSUMER_NO_BEG; i<CONSUMER_NO_END; i++ )) do task_exe "${i}" "${HOST_ID}" & done else # Otherwise, start a fixed number of workers echo "Starting ${WORKERS} task executor(s) on host '${HOST_ID}'..." for (( i=0; i<WORKERS; i++ )) do task_exe "${i}" "${HOST_ID}" & done fi fi wait
最新发布
06-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值