📄 rc_ctl_main.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 + -