⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rc_ctl_main.c

📁 epoll机制的收发程序 只能在2.6内核上使用
💻 C
字号:
/*
 * 文 件 名:rc_ctl_main.c
 * 功    能:链接控制部分的主函数
 * 作    者:马云龙
 * E_mail : mayunlong21@163.com
 * 开始时间:2007-4-23 16:05
 * 结束时间:2007-4-27 13:12
 * 修改时间:
 */
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<unistd.h>
#include	<sys/socket.h>
#include	<sys/epoll.h>
#include	<netinet/in.h>
#include	<arpa/inet.h>
#include	<fcntl.h>
#include	<unistd.h>
#include	<stdio.h>
#include	<pthread.h>
#include	<errno.h>
#include	<sys/ioctl.h>
#include	<mcheck.h>
#include	<signal.h>


#include	"rc_pub_define.h"
#include	"rc_pub_type.h"
#include	"rc_pub_path.h"
#include	"rc_pub_net.h"
#include	"rc_pub_file.h"
#include	"rc_pub_log.h"
#include	"rc_pub_time.h"
#include	"rc_pub_epoll.h"

#include	"rc_ctl_define.h"
#include	"rc_ctl_table.h"
#include	"rc_ctl_net.h"
#include	"rc_ctl_fifo.h"
#include	"rc_ctl_mysql.h"

#include	"include/mysql.h"
#include	"rc_mysql_util.h"

#define		TIME_SEC_OPT_NO			120	//没有任何操作的最长时间


struct_msg_con		*head_con = NULL;//摄像机链接信息的结构体头指针
struct_msg_atx		*head_atx = NULL;//控件链接信息的结构体头指针
int					port_atx;//监听控件的端口
int					port_cam;//监听摄像机的端口

unsigned char		space_delay;//链接间隔

int					port_video;//视频端口
char				ip_video[16];//视频服务器ip

int					epfd_cam;
int					epfd_atx;

pthread_mutex_t		mutex_r_cam = PTHREAD_MUTEX_INITIALIZER;//读摄像机任务队列的互斥锁
pthread_mutex_t		mutex_w_cam = PTHREAD_MUTEX_INITIALIZER;//写摄像机任务队列的互斥锁
pthread_cond_t		cond_r_cam = PTHREAD_COND_INITIALIZER;//读摄像机任务线程要使用的条件变量
pthread_cond_t		cond_w_cam = PTHREAD_COND_INITIALIZER;//写摄像机任务线程要使用的条件变量

pthread_mutex_t		mutex_r_atx = PTHREAD_MUTEX_INITIALIZER;//读控件任务队列的互斥锁
pthread_mutex_t		mutex_w_atx = PTHREAD_MUTEX_INITIALIZER;//写控件任务队列的互斥锁
pthread_cond_t		cond_r_atx = PTHREAD_COND_INITIALIZER;//读控件任务线程要使用的条件变量
pthread_cond_t		cond_w_atx = PTHREAD_COND_INITIALIZER;//写控件任务线程要使用的条件变量


pthread_mutex_t		mutex_con_t = PTHREAD_MUTEX_INITIALIZER;//摄像机链接链表的互斥锁
pthread_mutex_t		mutex_con_atx = PTHREAD_MUTEX_INITIALIZER;//控件链接链表的互斥锁


struct_task_net_r	*task_r_cam = NULL;//网络读摄像机任务队列头指针
struct_task_net_w	*task_w_cam = NULL;//网络写摄像机任务队列头指针
struct_task_sended	*task_sended = NULL;//已经发送过的任务队列的头指针(只对摄像机有用)

struct_task_net_r	*task_r_atx = NULL;//网络读控件任务队列头指针
struct_task_net_w	*task_w_atx = NULL;//网络写控件任务队列头指针


int rc_clear()
{
	char command[16];
	
	bzero(command, sizeof(command));
	sprintf(command, "clear");
	system(command);
	return 0;
}

/*
 * 功  能:设置最大的链接数
 * 参  数:num:最大链接数
 * 返回值:直接返回0
 */
int rc_set_num_socket(unsigned int num)
{
	unsigned char		command[32];
	
	bzero(command, sizeof(command));
	sprintf(command, "ulimit -n %u", num);
	
	return 0;
}

/*
 * 功  能:检测某一摄像机操作是否超时
 * 参  数:nowtime:现在时间
 * 返回值:返回操作超时的摄像机的台数
 */
int rc_check_cam(unsigned long int	nowtime)
{
	int					ret;
	int					sockfd;
	struct_msg_con		*lnk;
	
	ret = 0;
	pthread_mutex_lock(&mutex_con_t);
	lnk = head_con;
	while(1)
	{
		if(lnk != NULL)
		{
			if((nowtime - lnk->lasttime) >= TIME_SEC_OPT_NO)
			{
				ret++;
				sockfd = lnk->sockfd;
				rc_fd_del(epfd_cam, sockfd);
				
				rc_del_connection_one(&head_con, sockfd);
				
				pthread_mutex_lock(&mutex_w_cam);
				rc_del_task_w_one(&task_w_cam, sockfd);
				pthread_mutex_unlock(&mutex_w_cam);
				lnk = head_con;
				continue;
			}
		}
		else
			break;
		lnk = lnk->next;
	}
	pthread_mutex_unlock(&mutex_con_t);
	return ret;
}

/*
 * 功  能:检测某一控件操作是否超时
 * 参  数:nowtime:现在时间
 * 返回值:返回操作超时的控件的个数
 */
int rc_check_atx(unsigned long int	nowtime)
{
	int					ret;
	int					sockfd;
	struct_msg_atx		*lnk;
	
	ret = 0;
	pthread_mutex_lock(&mutex_con_atx);
	lnk = head_atx;
	while(1)
	{
		if(lnk != NULL)
		{
			if((nowtime - lnk->lasttime) >= TIME_SEC_OPT_NO)
			{
				ret++;
				sockfd = lnk->sockfd;
				rc_fd_del(epfd_cam, sockfd);
				
				rc_del_atx_one(&head_atx, sockfd);
				
				pthread_mutex_lock(&mutex_w_atx);
				rc_del_task_w_one(&task_w_atx, sockfd);
				pthread_mutex_unlock(&mutex_w_atx);
				lnk = head_atx;
				continue;
			}
		}
		else
			break;
		lnk = lnk->next;
	}
	pthread_mutex_unlock(&mutex_con_atx);
	return ret;
}


/*
 * 功  能:检测长时间没有操作的socket
 * 参  数:msg:线程的入口参数
 * 返回值:永不退出
 */
int rc_pthread_timer(char *msg)
{
	unsigned long int	nowtime;
	
	while(1)
	{
		sleep(TIME_SEC_OPT_NO);
		nowtime = rc_sec_now();
		rc_check_cam(nowtime);
		rc_check_atx(nowtime);
	}
	pthread_exit(NULL);
	return 0;
}

void rc_close_socket(int signum, siginfo_t *info, void *myact)
{
	return ;
}

//#define		DEBUG
/*
 * 说  明:链接控制的主函数
 */
int main(int argc, char **argv)
{
	int					res;
	int					len;
	
	char				temp[256];
	
	pthread_t			tid_timer;
	pthread_t			tid_fifo;//读管道用的线程id
	pthread_t			tid_atxs;//控件相关的主线程id
	
	struct sigaction		signalact;
	
//	rc_msg_alarm(10, "0123456", NULL);
//	return 0;
	
	sigemptyset(&signalact.sa_mask);
	sigfillset(&signalact.sa_mask);
	sigdelset(&signalact.sa_mask, SIGINT);//允许接收键盘发送来的终止信号
	sigdelset(&signalact.sa_mask, SIGSEGV);//允许接收段错误的信号
	sigprocmask(SIG_BLOCK, &signalact.sa_mask, NULL);
	signalact.sa_sigaction = rc_close_socket;//三参数信号处理函数
	signalact.sa_flags = SA_SIGINFO;//信息传递开关
	
	bzero(path_log, sizeof(path_log));
	rc_get_info(NAME_FILE_INI_CTL, KEY_PATH_LOG_CTL, path_log);
	if(strlen(path_log) < 1)
		strcpy(path_log, DEFAULT_PATH_LOG_CTL);
	
	rc_create_dir(path_log, 0777);//创建日志目录
	rc_create_dir(PATH_CONNECT_FIFO, 0777);//创建控制端使用的目录
	
	rc_log_init(TYPE_LOG_CTL);
	
	rc_set_num_socket(MAX_NUM_SOCKET);
	
	
	/* 链接数据库 */
#ifdef		MYSQL_USED_YES
	res = db_connect(&mysql, NAME_FILE_CONFIG_MTSQL, NAME_MYSQL);
	if(res == -1)
	{
		rc_add_log(__FILE__, __FUNCTION__, __LINE__, KEY_LOG_MYSQL, "mysql connect error!");
		return -1;
	}
#endif
	
	
	res = pthread_create(&tid_timer, NULL, (void *)rc_pthread_timer, NULL);
	if(res != 0)
	{
		printf("%s %d Create timer pthread error!\n", __FILE__, __LINE__);
		exit(-1);
	}
	pthread_detach(tid_timer);
	
	
	/* 获取摄像机尚未注册时的链接间隔 */
	bzero(temp, sizeof(temp));
	res = rc_get_info(NAME_FILE_INI_CTL, KEY_SPACE_CONNECT_CTL, temp);
	if(res >= 0)
	{
		space_delay = atoi(temp);
	}
	else
		space_delay = SPACE_DELAY_LINK_MIN;
	
	
	/* 获取视频控制端监听摄像机的端口 */
	bzero(temp, sizeof(temp));
	res = rc_get_info(NAME_FILE_INI_CTL, KEY_PORT_SERVER_CAM, temp);
	port_cam = 0;
	if(res >= 0)
	{
		port_cam = atoi(temp);
	}
	if(port_cam <= 0)
	{
		port_cam = PORT_LISTEN_CON_CAM;
	}

	/* 获取视频控制端监听控件的端口 */
	bzero(temp, sizeof(temp));
	res = rc_get_info(NAME_FILE_INI_CTL, KEY_PORT_SERVER_ATX, temp);
	port_atx = 0;
	if(res >= 0)
	{
		port_atx = atoi(temp);
	}
	if(port_atx <= 0)
	{
		port_atx = PORT_LISTEN_CON_ATX;
	}
	
	
	/* 获取视频转发端监听的端口 */
	bzero(temp, sizeof(temp));
	res = rc_get_info(NAME_FILE_INI_CTL, KEY_PORT_SERVER_VIDEO, temp);
	if(res >= 0)
	{
		port_video = atoi(temp);
		if(port_video <= 0)
			port_video = PORT_LISTEN_VIDEO;
	}
	else
		port_video = PORT_LISTEN_VIDEO;
	
	/* 获取视频转发端服务器的ip地址 */
	bzero(temp, sizeof(temp));
	bzero(ip_video, sizeof(ip_video));
	res = rc_get_info(NAME_FILE_INI_CTL, KEY_IP_SERVER_VIDEO, temp);
	if(res >= 0)
	{
		len = strlen(temp);
		if((len <= 15) && (len >= 7))
			strcpy(ip_video, temp);
	}
	len = strlen(ip_video);
	if((len < 7) || (len > 15))
	{
		printf("%s %d Video server ip error!\n", __FILE__, __LINE__);
		exit(-1);
	}
	
	/* 初始化各种互斥锁 */
	pthread_mutex_init(&mutex_con_t, NULL);
	pthread_mutex_init(&mutex_con_atx, NULL);
	pthread_mutex_init(&mutex_r_cam, NULL);
	pthread_mutex_init(&mutex_w_cam, NULL);
	pthread_mutex_init(&mutex_r_atx, NULL);
	pthread_mutex_init(&mutex_w_atx, NULL);
	
	/* 初始化各种条件变量 */
	pthread_cond_init(&cond_r_cam, NULL);
	pthread_cond_init(&cond_w_cam, NULL);
	pthread_cond_init(&cond_r_atx, NULL);
	pthread_cond_init(&cond_w_atx, NULL);
	
	
	/* 初始化用于读管道的线程 */
	res = pthread_create(&tid_fifo, NULL, (void *)rc_pthread_fifo_r, (void *)NULL);
	if(res != 0)
	{
		printf("%s %d Create read fifo thread error!\n", __FILE__, __LINE__);
		exit(-2);
	}
	pthread_detach(tid_fifo);
	
	rc_clear();//清除屏幕
	
	/* 初始化用于控件的线程 */
	res = pthread_create(&tid_atxs, NULL, (void *)rc_thread_atx, (void *)NULL);
	if(res != 0)
	{
		printf("%s %d Create atxs thread error!\n", __FILE__, __LINE__);
		exit(-2);
	}
	pthread_detach(tid_atxs);
	/* 摄像机的相关操作 */
	res = rc_thread_cam(NULL);
	mysql_close(&mysql);
	exit(0);
}








⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -