基于libevent2.0的ministored的http框架--server端

来源:互联网 发布:易语言充值源码 编辑:程序博客网 时间:2024/04/30 19:15
转自http://blog.csdn.net/sunnydogzhou/article/details/6438122

将Ministored从libevent1.4升级到2.0以后,花了两天额外的时间来做调试这个http的框架。

 

按照开发的设想,这个ministored支持四个基本的操作put、get、delete、status;在经过几个版本的改动以后,协议如下:

1)数据通过post的方式提交

2)各个基本操作通过一个自定义的Http的头method来区分。而client和server之间的传送的二进制数据通过base64编码以后的字符串发送。数据附加在post操作提交的字符缓冲区中。

     2.1 put操作需要的数据key value,解码以后,按照key和value的大小直接二进制拷贝,server并不关心数据的具体类型

     2.2 get操作接收client发送的key,解码,取出对应的数据以后,base64编码,发送给client

     2.3 delete操作接收client发送的key,解码,删除数据

     2.4 status操作直接返回当前Ministore状态的描述字符串

3)各个操作的结果通过自定义的响应头"result"返回

 

下面是部分的代码,限于篇幅,就不完全展开了。

 

[cpp] view plaincopy
  1. #include <event2/event.h>  
  2. #include <event2/buffer.h>  
  3. #include <event2/http.h>  
  4. #include <event2/http_struct.h>  
  5. #include <event2/keyvalq_struct.h>  
  6. #include "base64.h"  
  7. struct ministored_handler_param{  
  8.     int key_size;  
  9.     int value_size;  
  10. };  
  11. void ministored_handler(struct evhttp_request *req, void *arg){  
  12.     struct ministored_handler_param *param = (struct ministored_handler_param *) arg;  
  13.     struct evbuffer * buf;  
  14.     buf = evbuffer_new();  
  15.      
  16.     const char * ministored_input_opt = evhttp_find_header(req->input_headers,"method");  
  17.     fprintf(stdout,"method from client,%s/n",ministored_input_opt);  
  18.     evhttp_add_header(req->output_headers,"Content-Type","text/plain");     
  19.     evhttp_add_header(req->output_headers,"Connection","keep-alive");  
  20.     evhttp_add_header(req->output_headers,"Cache_Control","no-cache");  
  21.     if( NULL != ministored_input_opt ){  
  22.         if( strcmp(ministored_input_opt,"put") == 0 ){  
  23.             int buffer_data_len;  
  24.             buffer_data_len = evbuffer_get_length(req->input_buffer);  
  25.             if( buffer_data_len > 0 ){  
  26.              
  27.                 char * buffer_data = (char * ) malloc(buffer_data_len  + 1);  
  28.                 memset(buffer_data,'/0',buffer_data_len + 1);  
  29.                 evbuffer_copyout(req->input_buffer,buffer_data,buffer_data_len);  
  30.                 fprintf(stdout,"data:%s/n",buffer_data);  
  31.                 fprintf(stdout,"length:%d/n",buffer_data_len);  
  32.                 char *decoded_data = (char*) malloc (sizeof(char) * 200);  
  33.                 int decoded_len    = decode(buffer_data,buffer_data_len,decoded_data);  
  34.                 if( NULL != decoded_data){  
  35.                     char * ministored_key = (char*) malloc( sizeofchar) * (param->key_size + 1) );  
  36.                     memset(ministored_key,'/0',param->key_size + 1);  
  37.                     memcpy(ministored_key, decoded_data, param->key_size);  
  38.                     char *ministored_value = (char*)malloc( sizeof(char) * (param->value_size + 1) );  
  39.                     memset(ministored_value,'/0', param->value_size + 1);  
  40.                     memcpy(ministored_value, decoded_data + param->value_size, param->value_size);  
  41.                     //todo,put into ministore  
  42.                     long key,value;  
  43.                     memcpy(&key,ministored_key,8);  
  44.                     memcpy(&value,ministored_value,8);  
  45.                     printf("key:%ld/tvaleu:%ld/n",key,value);  
  46.                     free( ministored_key );  
  47.                     free( ministored_value );  
  48.                     evhttp_add_header(req->output_headers,"result","MINISTORED_OK");     
  49.                 }else{  
  50.                     evhttp_add_header(req->output_headers,"result","MINISTORED_INTENAL_ERROR");     
  51.                 }  
  52.                 free(buffer_data);  
  53.                 free(decoded_data);  
  54.             }else{  
  55.                 evhttp_add_header(req->output_headers,"result","MINISTORED_NO_DATA");     
  56.             }  
  57.         }  
  58.         if(strcmp(ministored_input_opt,"get")== 0 ){  
  59.                 ... ...;             
  60.         }  
  61.         if(strcmp(ministored_input_opt,"delete")== 0 ){  
  62.              
  63.                 ... ...;  
  64.         }  
  65.         if( strcmp(ministored_input_opt,"status" ) == 0){  
  66.             int size;  
  67.             int used;  
  68.             evbuffer_add_printf(buf,"Ministored Simple Service");  
  69.             evbuffer_add_printf(buf,"--------------------------");  
  70.             evbuffer_add_printf(buf,"size:%d",size);         
  71.             evbuffer_add_printf(buf,"used:%d",used);  
  72.         }  
  73.         evhttp_send_reply(req,HTTP_OK,"OK",buf);  
  74.         evbuffer_free(buf);  
  75.     }  
  76. }  
  77. void kill_signal(const int sig){  
  78.     exit(0);     
  79. }  
  80. void show_help(){  
  81.     char *b ="-----------------------------------------"  
  82.             "HTTP SIMPLE MiniStore Service /n"  
  83.             "-l <ip_addr>    IP Address/n"  
  84.             "-p <num>        TCP Port/n"  
  85.             "-d                run as a daemon/n";  
  86.     fprintf(stderr,b,strlen(b));  
  87. }  
  88. int main(int argc,char **argv){  
  89.     char * ministored_listen_ip ="0.0,0.0";  
  90.     int ministored_listen_port = 1314;  
  91.     bool ministored_daemon = false;  
  92.     int    ministored_time_out = 3;  
  93.      
  94.     char * ministored_shm_path = "/var/log/temp";  
  95.     int ministored_mem_size = 100*1024*1024;  
  96.     float ministored_mem_capacity= 0.8;  
  97.     int ministored_key_size = 8;  
  98.     int ministored_value_size = 8;  
  99.     int ministore_work_mode = 1;  
  100.      
  101.     int c;  
  102.     while ((c = getopt(argc, argv, "l:p:x:t:s:c:m:i:d:h:k:v")) != -1) {  
  103.         switch (c) {  
  104.             case 'l':  
  105.                 ministored_listen_ip = strdup(optarg);  
  106.                 break;     
  107.             case 'p':  
  108.                 ministored_listen_port = atoi(optarg);  
  109.                 break;     
  110.             case 'd':  
  111.                 ministored_daemon=true;  
  112.                 break;  
  113.             case 't':  
  114.                 ministored_time_out = atoi(optarg);  
  115.                 break;  
  116.             case 'k':  
  117.                 ministored_key_size = atoi(optarg);  
  118.                 break;  
  119.             case 'v':  
  120.                 ministored_value_size = atoi(optarg);  
  121.                 break;  
  122.             case 'h':  
  123.             default:  
  124.                 show_help();  
  125.         }  
  126.     }  
  127.     // run as deamon  
  128.     if( ministored_daemon ){  
  129.         pid_t pid;  
  130.         pid =fork();  
  131.         if( pid < 0 ){  
  132.             exit(-1);     
  133.         }  
  134.         if(pid > 0){  
  135.             exit(0);     
  136.         }  
  137.     }  
  138.     signal(SIGPIPE,SIG_IGN);  
  139.     signal(SIGINT,kill_signal);  
  140.     signal(SIGKILL,kill_signal);  
  141.     signal(SIGQUIT,kill_signal);  
  142.     signal(SIGTERM,kill_signal);  
  143.     signal(SIGHUP,kill_signal);  
  144.     struct event_base *base;  
  145.     struct evhttp *httpd;  
  146.     struct evhttp_bound_socket *handle;  
  147.    
  148.     base = event_base_new();  
  149.     if (!base) {  
  150.         fprintf(stderr, "Couldn't create an event_base: exiting/n");  
  151.         return 1;  
  152.     }  
  153.    
  154.     /* Create a new evhttp object to handle requests. */  
  155.     httpd = evhttp_new(base);  
  156.     if (!httpd) {  
  157.         fprintf(stderr, "couldn't create evhttp. Exiting./n");  
  158.         return 1;  
  159.     }  
  160.     evhttp_set_timeout(httpd,ministored_time_out);  
  161.     struct ministored_handler_param *param = (struct ministored_handler_param*) malloc(sizeof(struct ministored_handler_param));     
  162.     param->key_size = ministored_key_size;  
  163.     param->value_size = ministored_value_size;  
  164.     // set the call back function  
  165.     evhttp_set_gencb(httpd,ministored_handler,param);  
  166.     /* Now we tell the evhttp what port to listen on */  
  167.     handle = evhttp_bind_socket_with_handle(httpd,ministored_listen_ip , ministored_listen_port);  
  168.     if (!handle) {  
  169.         fprintf(stderr, "couldn't bind to port %d. Exiting./n",  
  170.                 (int)ministored_listen_port);  
  171.         return 1;  
  172.     }  
  173.     event_base_dispatch(base);  
  174.     evhttp_free(httpd);  
  175.     return 0;  
  176. }  

这个server框架不仅适用ministored,可以将它搭配任意的存储工具来做网络端的存储。比如BDB、tokyo cabinet来做一个定制的大容量的缓存。

原创粉丝点击