summaryrefslogtreecommitdiff
path: root/http_check/src/http_check.c
diff options
context:
space:
mode:
Diffstat (limited to 'http_check/src/http_check.c')
-rw-r--r--http_check/src/http_check.c464
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;
+}
+
+