diff options
Diffstat (limited to 'http_check/src/http_check.c')
| -rw-r--r-- | http_check/src/http_check.c | 464 |
1 files changed, 464 insertions, 0 deletions
diff --git a/http_check/src/http_check.c b/http_check/src/http_check.c new file mode 100644 index 0000000..5c24e6a --- /dev/null +++ b/http_check/src/http_check.c @@ -0,0 +1,464 @@ +#include <stdio.h> +#include <stdlib.h> +#include <evhttp.h> +#include <event.h> +#include <string.h> +#include <time.h> +#include <sys/sysinfo.h> +#include <unistd.h> +#include <arpa/inet.h> +#include <linux/rtnetlink.h> +#include <net/if.h> +#include <ctype.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> +#include <printf.h> +#include <signal.h> +#include <dirent.h> +#include <sys/types.h> +//#include "cJSON/cJSON.h" +#include "cJSON.h" +#include "MESA/MESA_prof_load.h" +#include "MESA/stream.h" +#include "MESA/MESA_prof_load.h" +#include "MESA/MESA_handle_logger.h" +#include "MESA/MESA_htable.h" +#include "MESA/MESA_list.h" + +#define BUFSIZE 8192 +#define MAX_LOG_PATH_LEN 256 +#define CPU_START_POS 14 /* stat文件的有效起始行数 */ +int g_http_port; +char g_http_address[MAX_LOG_PATH_LEN]=""; +//const char *http_check_conf_file = "./conf/http_check/http_check.conf"; +const char *http_check_conf_file = "/home/mesasoft/sapp/plug/business/http_check/http_check.conf"; + +struct route_info +{ + u_int dstAddr; + u_int srcAddr; + u_int gateWay; + char ifName[IF_NAMESIZE]; +}; + +//************************************cpu占用******************** +// CPU占用率计算: +// 1、读取/proc/pid/stat文件,其中记录了从开机到现在,本进程所占用的CPU时间(单位jiffies) +// 2、然后再读取/proc/stat文件,其中记录了从开机到现在,系统所占用的CPU时间(单位jiffies) +// 3、取两个时间点,这两个时间点的进程耗时差,除以系统耗时差,得到的就是该进程的CPU占用率 + +//在字符串中寻找第N次空格出现的地方 +char *get_items_by_pos(char *buff, unsigned int numb) +{ + char *crpos; + int i, ttlen, count; + + crpos = buff; + ttlen = strlen(buff); + count = 0; + + for (i = 0; i < ttlen; i++) + { + if (' ' == *crpos) + { /* 以空格为标记符进行识别 */ + count++; + if (count == (numb - 1)) + { /* 全部个数都找完了 */ + crpos++; + break; + } + } + crpos++; + } + + return crpos; +} + +//获取当前进程的CPU时间 +long get_pro_cpu_time(unsigned int pid) +{ + FILE *fd; + char *vpos, buff[1024]; + long utime, stime, cutime, cstime; + + sprintf(buff, "/proc/%d/stat", pid); + + fd = fopen(buff, "r"); + assert(fd != NULL); + assert(fgets(buff, sizeof(buff), fd) != NULL); + + vpos = get_items_by_pos(buff, CPU_START_POS); + sscanf(vpos, "%ld %ld %ld %ld", &utime, &stime, &cutime, &cstime); + //printf("get_data2:%ld %ld %ld %ld\n", utime, stime, cutime, cstime); + fclose(fd); + + return (utime + stime + cutime + cstime); + //return (utime + stime); +} + +//获取整个系统的CPU时间 +long get_sys_cpu_time(void) +{ + FILE *fd; + char name[32], buff[1024]; + long user, nice, syst, idle; + + fd = fopen("/proc/stat", "r"); + assert(fd != NULL); + assert(fgets(buff, sizeof(buff), fd) != NULL); + + sscanf(buff, "%s %ld %ld %ld %ld", name, &user, &nice, &syst, &idle); + //printf("get_data1:%s %ld %ld %ld %ld\n", name, user, nice, syst, idle); + fclose(fd); + + return (user + nice + syst + idle); + //return (user + syst); +} + +//获取进程的CPU使用率 +float get_cpu_stat(unsigned int pid) +{ + float ratio; + long s_cur_pro_cpu, s_pre_pro_cpu; /* 指定程序的本轮/前轮CPU时间 */ + long s_cur_sys_cpu, s_pre_sys_cpu; /* 整个系统的本轮/前轮CPU时间 */ + + s_pre_pro_cpu = get_pro_cpu_time(pid); + s_pre_sys_cpu = get_sys_cpu_time(); + + sleep(1); + s_cur_pro_cpu = get_pro_cpu_time(pid); + s_cur_sys_cpu = get_sys_cpu_time(); + if ((s_cur_pro_cpu == s_pre_pro_cpu) || (s_cur_sys_cpu == s_pre_sys_cpu) || (s_cur_pro_cpu == 0) || (s_cur_sys_cpu == 0)) { + ratio = 0; + } else { + ratio = (100.0 * (s_cur_pro_cpu - s_pre_pro_cpu)) / (s_cur_sys_cpu - s_pre_sys_cpu); + } + + return ratio; +} + +//获取默认网关地址 +int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId) +{ + struct nlmsghdr *nlHdr; + int readLen = 0, msgLen = 0; + do{ + //收到内核的应答 + if((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0) + { + perror("SOCK READ: "); + return -1; + } + + nlHdr = (struct nlmsghdr *)bufPtr; + //检查header是否有效 + if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) + { + perror("Error in recieved packet"); + return -1; + } + + if(nlHdr->nlmsg_type == NLMSG_DONE) + { + break; + } + else + { + bufPtr += readLen; + msgLen += readLen; + } + + if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) + { + break; + } + } while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId)); + + return msgLen; +} + +//分析返回的路由信息 +void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo,char *gateway) +{ + struct rtmsg *rtMsg; + struct rtattr *rtAttr; + int rtLen; + char *tempBuf = NULL; + struct in_addr dst; + struct in_addr gate; + + tempBuf = (char *)malloc(100); + rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr); + // If the route is not for AF_INET or does not belong to main routing table + //then return. + if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) + return; + + rtAttr = (struct rtattr *)RTM_RTA(rtMsg); + rtLen = RTM_PAYLOAD(nlHdr); + + for(;RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen)) + { + switch(rtAttr->rta_type) + { + case RTA_OIF: + if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName); + break; + case RTA_GATEWAY: + rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr); + break; + case RTA_PREFSRC: + rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr); + break; + case RTA_DST: + rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr); + break; + } + } + dst.s_addr = rtInfo->dstAddr; + if (strstr((char *)inet_ntoa(dst), "0.0.0.0")) + { + //printf("oif:%s",rtInfo->ifName); + gate.s_addr = rtInfo->gateWay; + sprintf(gateway, (char *)inet_ntoa(gate)); + //printf("%s\n",gateway); + gate.s_addr = rtInfo->srcAddr; + //printf("src:%s\n",(char *)inet_ntoa(gate)); + gate.s_addr = rtInfo->dstAddr; + //printf("dst:%s\n",(char *)inet_ntoa(gate)); + } + free(tempBuf); + + return; +} + +int get_gateway(char *gateway) +{ + struct nlmsghdr *nlMsg; + //struct rtmsg *rtMsg; + struct route_info *rtInfo; + char msgBuf[BUFSIZE]; + int sock, len, msgSeq = 0; + + if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) + { + perror("Socket Creation: "); + return -1; + } + + memset(msgBuf, 0, BUFSIZE); + nlMsg = (struct nlmsghdr *)msgBuf; + //rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg); + nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message. + nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table . + nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump. + nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet. + nlMsg->nlmsg_pid = getpid(); // PID of process sending the request. + + if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) + { + printf("Write To Socket Failed…\n"); + return -1; + } + + if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) + { + printf("Read From Socket Failed…\n"); + return -1; + } + + rtInfo = (struct route_info *)malloc(sizeof(struct route_info)); + for(;NLMSG_OK(nlMsg,len);nlMsg = NLMSG_NEXT(nlMsg,len)) + { + memset(rtInfo, 0, sizeof(struct route_info)); + parseRoutes(nlMsg, rtInfo,gateway); + } + free(rtInfo); + close(sock); + + return 0; +} + +//status回响应 +void http_handler_status_msg(struct evhttp_request *req,void *arg) +{ + struct sysinfo info; + time_t cur_time = 0; + time_t boot_time = 0; + struct tm *ptm = NULL; + unsigned int run_days,run_hour,run_minute,run_second; + pid_t process_id; + + //启动时间,启动时长 + if (sysinfo(&info)) + { + fprintf(stderr, "Failed to get sysinfo, errno:%u, reason:%s\n", + errno, strerror(errno)); + return ; + } + time(&cur_time); + if (cur_time > info.uptime) + { + boot_time = cur_time - info.uptime; + } + else + { + boot_time = info.uptime - cur_time; + } + ptm = localtime(&boot_time); + /*printf("System boot time:%d-%-d-%d %d:%d:%d\n", ptm->tm_year + 1900, + ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);*/ + + run_days=info.uptime / 86400; + run_hour=(info.uptime % 86400)/3600; + run_minute=(info.uptime % 3600)/60; + run_second=info.uptime % 60; + //printf("system running time:%dday %dhour %dminute %dsecond\n",run_days,run_hour,run_minute,run_second); + + //进程号 + process_id = getpid(); + //printf("process id:%d\n", process_id); + + //默认网关地址 + char buff[256]; + get_gateway(buff); + //printf("gateway:%s\n",buff); + + //内存(虚存,实存) + unsigned int n_rss, n_resident, n_share, n_text, n_lib, n_data, n_dt; + char buf[256]; + char buf1[256]; + char buf2[256]; + char buf3[256]; + FILE *f = fopen("/proc/self/statm","r"); + + if(f) + { + fscanf(f,"%u%u%u%u%u%u%u",&n_rss,&n_resident,&n_share,&n_text,&n_lib,&n_data,&n_dt); + fclose(f); + } + else + { + printf("open /proc/self/statm failed!"); + return; + } + n_rss = n_rss * 4; + n_resident = n_resident *4; + + sprintf(buf, "VmSize=%ukB, VmRss=%ukB", n_rss, n_resident); + //printf("memory info:%s\n",buf); + + //cpu + float cpu_rate; + unsigned int cpu_num; + cpu_rate = get_cpu_stat(process_id); + cpu_num = get_nprocs();//获取可用cpu数 + //printf("cpu usage = %f\n", cpu_rate*cpu_num); + + struct evbuffer *retbuff = NULL; + retbuff = evbuffer_new(); + if(retbuff == NULL) + { + printf("====line:%d,%s\n",__LINE__,"retbuff is null."); + return; + } + sprintf(buf1, "%d-%-d-%d %d:%d:%d", ptm->tm_year + 1900,ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); + sprintf(buf2, "%ddays %dhours %dminutes %dseconds", run_days,run_hour,run_minute,run_second); + sprintf(buf3, "%f", cpu_rate*cpu_num); + cJSON * root = cJSON_CreateObject(); + + //根节点下添加 + cJSON_AddItemToObject(root, "boot time", cJSON_CreateString(buf1)); + cJSON_AddItemToObject(root, "running time", cJSON_CreateString(buf2)); + cJSON_AddItemToObject(root, "process id", cJSON_CreateNumber(process_id)); + cJSON_AddItemToObject(root, "server ip", cJSON_CreateString(g_http_address)); + cJSON_AddItemToObject(root, "default gateway", cJSON_CreateString(buff)); + cJSON_AddItemToObject(root, "memory info", cJSON_CreateString(buf)); + cJSON_AddItemToObject(root, "cpu usage", cJSON_CreateString(buf3)); + + printf("cjson_status_print:%s\n", cJSON_Print(root)); + + //evbuffer_add_printf(retbuff,"System boot time: %d-%-d-%d %d:%d:%d\r\nsystem running time:%dday %dhour %dminute %dsecond\r\nprocess id:%d\r\ngateway:%s\r\nmemory info:%s\r\ncpu% = %f\r\n", + // ptm->tm_year + 1900,ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, run_days,run_hour,run_minute,run_second,process_id,buff,buf,cpu_rate*cpu_num); + evbuffer_add_printf(retbuff,cJSON_Print(root)); + evhttp_send_reply(req,HTTP_OK,"OK",retbuff); + evbuffer_free(retbuff); + if(root) + { + cJSON_Delete(root); + } + + return; +} + +//keepalive回响应 +void http_handler_keepalive_msg(struct evhttp_request *req,void *arg) +{ + struct tm *local; + time_t tt; + tt=time(NULL); + local=localtime(&tt); + + struct evbuffer *retbuff = NULL; + retbuff = evbuffer_new(); + if(retbuff == NULL) + { + printf("====line:%d,%s\n",__LINE__,"retbuff is null."); + return; + } + + cJSON * root = cJSON_CreateObject(); + cJSON_AddItemToObject(root, "current time", cJSON_CreateString(asctime(local))); + printf("cjson_keepalive_print:%s\n", cJSON_Print(root)); + + evbuffer_add_printf(retbuff,cJSON_Print(root)); + evhttp_send_reply(req,HTTP_OK,"OK",retbuff); + evbuffer_free(retbuff); + if(root) + { + cJSON_Delete(root); + } + + return; +} + +//int main() +int http_check_init() +{ + struct evhttp *http_server = NULL; + //short http_port = 10000; + //char *http_addr = "0.0.0.0"; + + MESA_load_profile_int_def(http_check_conf_file, "HTTP", "SERVER_PORT", &g_http_port, 0); + MESA_load_profile_string_def(http_check_conf_file, "HTTP", "SERVER_IP", g_http_address, MAX_LOG_PATH_LEN, NULL); + printf("*v1*******read_ip:%s,read_port:%d\n",g_http_address, g_http_port); + //初始化 + event_init(); + //启动http服务端 + http_server = evhttp_start(g_http_address,g_http_port); + if(http_server == NULL) + { + printf("====line:%d,%s\n",__LINE__,"http server start failed."); + return -1; + } + + //设置请求超时时间(s) + evhttp_set_timeout(http_server,100); + //设置事件处理函数,evhttp_set_cb针对每一个事件(请求)注册一个处理函数, + //区别于evhttp_set_gencb函数,是对所有请求设置一个统一的处理函数 + evhttp_set_cb(http_server,"/status",http_handler_status_msg,NULL);//为特定的URI指定callback + evhttp_set_cb(http_server,"/keepalive",http_handler_keepalive_msg,NULL); + //循环监听 + event_dispatch(); + evhttp_free(http_server); + + return 0; +} + +void http_check_destory() +{ + return; +} + + |
