zl程序教程

您现在的位置是:首页 >  后端

当前栏目

libevent库的使用--定时器的使用实例

实例 使用 -- 定时器 libevent
2023-06-13 09:15:14 时间

复制代码代码如下:


#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<event.h>
#include<evhttp.h>

#defineRELOAD_TIMEOUT5
#defineDEFAULT_FILE"sample.html"

char*filedata;
time_tlasttime=0;
charfilename[80];
intcounter=0;

voidread_file()
{
 intsize=0;
 char*data;
 structstatbuf;

 stat(filename,&buf);

 if(buf.st_mtime>lasttime)
   {
     if(counter++)
       fprintf(stderr,"Reloadingfile:%s",filename);
     else
       fprintf(stderr,"Loadingfile:%s",filename);

     FILE*f=fopen(filename,"rb");
     if(f==NULL)
       {
         fprintf(stderr,"Couldn"topenfile\n");
         exit(1);
       }

     fseek(f,0,SEEK_END);
     size=ftell(f);
     fseek(f,0,SEEK_SET);
     data=(char*)malloc(size+1);
     fread(data,sizeof(char),size,f);
     filedata=(char*)malloc(size+1);
     strcpy(filedata,data);
     fclose(f);


     fprintf(stderr,"(%dbytes)\n",size);
     lasttime=buf.st_mtime;
   }
}

voidload_file()
{
 structevent*loadfile_event;
 structtimevaltv;

 read_file();

 tv.tv_sec=RELOAD_TIMEOUT;
 tv.tv_usec=0;

 loadfile_event=malloc(sizeof(structevent));

 evtimer_set(loadfile_event,
             load_file,
             loadfile_event);

 evtimer_add(loadfile_event,
             &tv);
}

voidgeneric_request_handler(structevhttp_request*req,void*arg)
{
 structevbuffer*evb=evbuffer_new();

 evbuffer_add_printf(evb,"%s",filedata);
 evhttp_send_reply(req,HTTP_OK,"Client",evb);
 evbuffer_free(evb);
}

intmain(intargc,char*argv[])
{
 short         http_port=8081;
 char         *http_addr="192.168.0.22";
 structevhttp*http_server=NULL;

 if(argc>1)
   {
     strcpy(filename,argv[1]);
     printf("Using%s\n",filename);
   }
 else
   {
     strcpy(filename,DEFAULT_FILE);
   }

 event_init();

 load_file();

 http_server=evhttp_start(http_addr,http_port);
 evhttp_set_gencb(http_server,generic_request_handler,NULL);

 fprintf(stderr,"Serverstartedonport%d\n",http_port);
 event_dispatch();
}

这个服务器的基本原理与前面的示例相同。首先,脚本设置一个HTTP服务器,它只响应对基本URL主机/端口组合的请求(不处理请求URI)。第一步是装载文件(read_file())。在装载最初的文件时和在计时器触发回调时都使用此函数。
read_file()函数使用stat()函数调用检查文件的修改时间,只有在上一次装载之后修改了文件的情况下,它才重新读取文件的内容。此函数通过调用fread()装载文件数据,把数据复制到另一个结构中,然后使用strcpy()把数据从装载的字符串转移到全局字符串中。
load_file()函数是触发计时器时调用的函数。它通过调用read_file()装载内容,然后使用RELOAD_TIMEOUT值设置计时器,作为尝试装载文件之前的秒数。libevent计时器使用timeval结构,允许按秒和毫秒指定计时器。计时器不是周期性的;当触发计时器事件时设置它,然后从事件队列中删除事件。
使用与前面的示例相同的格式编译代码:$gcc-obasichttpfilebasichttpfile.c-levent。
现在,创建作为数据使用的静态文件;默认文件是sample.html,但是可以通过命令行上的第一个参数指定任何文件(见清单6)。
清单6.创建作为数据使用的静态文件

复制代码代码如下:


$./basichttpfile
Loadingfile:sample.html(8046bytes)
Serverstartedonport8081

现在,程序可以接受请求了,重新装载计时器也启动了。如果修改sample.html的内容,应该会重新装载此文件并在日志中记录一个消息。例如,清单7中的输出显示初始装载和两次重新装载:
清单7.输出显示初始装载和两次重新装载

复制代码代码如下:
$./basichttpfile
Loadingfile:sample.html(8046bytes)
Serverstartedonport8081
Reloadingfile:sample.html(8047bytes)
Reloadingfile:sample.html(8048bytes)

注意,要想获得最大的收益,必须确保环境没有限制打开的文件描述符数量。可以使用ulimit命令修改限制(需要适当的权限或根访问)。具体的设置取决与您的OS,但是在Linux®上可以用-n选项设置打开的文件描述符(和网络套接字)的数量