服务器媒体事件和信号处理

Posted qianbo_insist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了服务器媒体事件和信号处理相关的知识,希望对你有一定的参考价值。

事件类型

总体来说,划分事件是为了在脚本中注册各类事件,从而向其他模块,可执行文件,通知各种异常和非异常的发生点,比如一个客户端链接上来,就是一个非异常发生点,超时脱线就是一个异常发生点。

架构上划分事件清楚,就可以更加方便地将流程整理清楚。事件可以分为
1 服务事件
2 会话session事件
3 服务状态事件,比如录像开始

switch(_type)
		
			// StreamEventType
			case EventType::ServerStarted:
			case EventType::HostCreated:
			case EventType::HostDeleted:
			case EventType::AppCreated:
			case EventType::AppDeleted:
			case EventType::StreamCreated:
			case EventType::StreamDeleted: 
			case EventType::StreamOriginLinkUpdated:
			case EventType::StreamOutputsUpdated:
				_category = EventCategory::StreamEventType;
				break;
			// SessionEventType
			case EventType::SessionConnected:
			case EventType::SessionDisconnected:
				_category = EventCategory::SessionEventType;
				break;
			// ActoinEventType
			case EventType::ApiCalled:
			case EventType::RecordingStarted:
			case EventType::RecordingStopped:
			case EventType::PushStarted:
			case EventType::PushStopped:
				_category = EventCategory::ActoinEventType;
				break;
			// NotificationEventType
			case EventType::Info:
			case EventType::Error:
				_category = EventCategory::NotificationEventType;
				break;
			// StatisticsEventType
			case EventType::ServerStat:
				_category = EventCategory::StatisticsEventType;
				break;
		

事件翻译

将事件翻译成可以认识的字符串

String Event::GetTypeString() const
	
		switch(_type)
		
			// StreamEventType
			case EventType::ServerStarted:
				return "ServerStarted";
			case EventType::HostCreated:
				return "HostCreated";
			case EventType::HostDeleted:
				return "HostDeleted";
			case EventType::AppCreated:
				return "AppCreated";
			case EventType::AppDeleted:
				return "AppDeleted";
			case EventType::StreamCreated:
				return "StreamCreated";
			case EventType::StreamDeleted: 
				return "StreamDeleted";
			case EventType::StreamOriginLinkUpdated:
				return "StreamOriginLinkUpdated";
			case EventType::StreamOutputsUpdated:
				return "StreamOutputsUpdated";
			// SessionEventType
			case EventType::SessionConnected:
				return "SessionConnected";
			case EventType::SessionDisconnected:
				return "SessionDisconnected";
			// ActoinEventType
			case EventType::ApiCalled:
				return "ApiCalled";
			case EventType::RecordingStarted:
				return "RecordingStarted";
			case EventType::RecordingStopped:
				return "RecordingStopped";
			case EventType::PushStarted:
				return "PushStarted";
			case EventType::PushStopped:
				return "PushStopped";
			// NotificationEventType
			case EventType::Info:
				return "Info";
			case EventType::Error:
				return "Error";
			// StatisticsEventType
			case EventType::ServerStat:
				return "ServerStat";
		

		return "";
	

事件翻译成json

为了通信解释,可以将事件翻译成json,如下代码所示

String Event::SerializeToJson() const
	
		Json::Value json_root;

		// Fill common values
		json_root["eventVersion"] = EVENT_VERSION;
		json_root["timestampMillis"] = _creation_time_msec;
		json_root["userKey"] = _server_metric->GetConfig()->GetAnalytics().GetUserKey().CStr();
		json_root["serverID"] = _server_metric->GetConfig()->GetID().CStr();
		
		// Fill root["event"]
		Json::Value &json_event = json_root["event"];
		json_event["type"] = GetTypeString().CStr();
		if(_message.IsEmpty() == false)
		
			json_event["message"] = _message.CStr();
		
		
		Json::Value &json_producer = json_event["producer"];
		FillProducer(json_producer);

		// Fill root["data"]
		Json::Value &json_data = json_root["data"];

		if(_category == EventCategory::StreamEventType)
		
			//TODO(Getroot): Implement this
			json_data["dataType"] = "Not Implemented";

			Json::Value &json_server_info = json_data["serverInfo"];
			FillServerInfo(json_server_info);
		
		else if(_category == EventCategory::StatisticsEventType)
		
			Json::Value &json_server_stat = json_data["serverStat"];
			FillServerStatistics(json_server_stat);
		

		Json::StreamWriterBuilder builder;
		/* 
			Default StreamWriterBuilder settings

		  	(*settings)["commentStyle"] = "All";
			(*settings)["indentation"] = "\\t";
			(*settings)["enableYAMLCompatibility"] = false;
			(*settings)["dropNullPlaceholders"] = false;
			(*settings)["useSpecialFloats"] = false;
			(*settings)["emitUTF8"] = false;
			(*settings)["precision"] = 17;
			(*settings)["precisionType"] = "significant";
		*/

		logtd("%s", json_root.toStyledString().c_str());

		builder["indentation"] = "";
		return Json::writeString(builder, json_root).c_str();
	

信号处理

信号是一种软件中断,提供了异步事件的处理机制,比如SIGCHLD,代表子进程终止信号,子进程终止后捕获该信号,处理子进程异常信息。

SIGUSR1 SIGUSR2 两个都是进程自定义信号,这些信号是给用户自定义用的,内核从来不发送他们,进程可以使用任何目的使用这两个信号。

接下来就是更多的信号处理,如下所示,信号就很多了

bool InitializeSignals()

	//	 1) SIGHUP		 2) SIGINT		 3) SIGQUIT		 4) SIGILL		 5) SIGTRAP
	//	 6) SIGABRT		 7) SIGBUS		 8) SIGFPE		 9) SIGKILL		10) SIGUSR1
	//	11) SIGSEGV		12) SIGUSR2		13) SIGPIPE		14) SIGALRM		15) SIGTERM
	//	16) SIGSTKFLT	17) SIGCHLD		18) SIGCONT		19) SIGSTOP		20) SIGTSTP
	//	21) SIGTTIN		22) SIGTTOU		23) SIGURG		24) SIGXCPU		25) SIGXFSZ
	//	26) SIGVTALRM	27) SIGPROF		28) SIGWINCH	29) SIGIO		30) SIGPWR
	//	31) SIGSYS		34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
	//	38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
	//	43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
	//	48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
	//	53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
	//	58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
	//	63) SIGRTMAX-1	64) SIGRTMAX

	return InitializeAbortSignal() &&
		   InitializeUser1Signal() &&
		   InitializeReloadSignal() &&
		   InitializeTerminateSignal();

信号处理程序举例

#include <stdio.h>

static void sigint_handle(int signo)

    printf("............................");
    exit(EXIT_SUCCESS);


int main(void)

  if(signal(SIGINT, sigint_handle) == SIG_ERR)
     fprintf(stderr,"can not handle\\n";
     exit(EXIT_FAILURE);
  
  for(;;)
  
     pause();
  
  return 0;

其中SIGINT是处理用户输入中断符号事件,比如调试使用ctrl+c,而pause是系统调用函数,将挂起程序,知道有信号,信号由内核发送给进程,从而唤醒系统进程。这个需要读者掌握多一些操作系统的原理了。

事件和信号结合

除了可以写脚本来处理,比如lua,或者javascript等,还可以将事件和信号联系起来,进程系统级别的调用,比如碰到SIGSEGV 内存处理异常,SIGXCPU 进程资源超限制等信号,我们收到这些信号后可以重启或关闭程序。

以上是关于服务器媒体事件和信号处理的主要内容,如果未能解决你的问题,请参考以下文章

CarEye 流媒体处理服务器

CarEye 流媒体处理服务器

CarEye 流媒体处理服务器

请问啥叫做回调函数

流媒体服务器 NTV Media Server G3 电视回看功能赏析

ITSM常见问题之:如何有效处理非工作时间和节假日发生的事件