第二章 C语言实例 —制作http服务器

    博客分类:

  • C语言参考与学习
C

任务:

1.制作http服务器,读取url提交的相关数据.

2.把读到的数据推入到队列中.

条件:

使用libevent的类库,所以先安装libevent

Sh代码
  1. tarzxvflibevent-2.0.12-stable.tar.gz
  2. cdlibevent-2.0.12-stable/
  3. ./configure--prefix=/usr/local/libevent-2.0.12-stable/
  4. make
  5. makeinstall
  6. cd../
tar zxvf libevent-2.0.12-stable.tar.gz
cd libevent-2.0.12-stable/
./configure --prefix=/usr/local/libevent-2.0.12-stable/
make
make install
cd ../

1.服务端简易代码如下

C代码
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<err.h>
  4. #include<event.h>
  5. #include<evhttp.h>
  6. voidhttp_handle(structevhttp_request*req,void*arg);/*HTTPRequestHandle*/
  7. intmain(){
  8. structevhttp*httpd;
  9. event_init();
  10. httpd=evhttp_start("0.0.0.0",2345);
  11. if(httpd==NULL){
  12. fprintf(stderr,"Error:Unabletolistenon%s:%d\n\n");
  13. exit(1);
  14. }
  15. evhttp_set_timeout(httpd,2000);
  16. evhttp_set_gencb(httpd,http_handle,NULL);
  17. event_dispatch();
  18. evhttp_free(httpd);
  19. return0;
  20. }
  21. voidhttp_handle(structevhttp_request*req,void*arg){
  22. structevbuffer*buf;
  23. buf=evbuffer_new();
  24. /*Responsetheclient*/
  25. evhttp_send_reply(req,HTTP_OK,"OK",buf);
  26. //evbuffer_add_printf(buf,"%s","HTTPSQS_AUTH_FAILED");
  27. /*Releasethememory*/
  28. evbuffer_free(buf);
  29. fprintf(stderr,"Send\n");
  30. }
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <event.h>
#include <evhttp.h>
void http_handle(struct evhttp_request *req, void *arg); /*  HTTP Request Handle  */
int main(){
struct evhttp *httpd;
event_init();
httpd = evhttp_start("0.0.0.0", 2345);
if (httpd == NULL) {
fprintf(stderr, "Error: Unable to listen on %s:%d\n\n");
exit(1);
}
evhttp_set_timeout(httpd, 2000);
evhttp_set_gencb(httpd, http_handle, NULL);
event_dispatch();
evhttp_free(httpd);
return 0;
}
void http_handle(struct evhttp_request *req, void *arg){
struct evbuffer *buf;
buf = evbuffer_new();
/*  Response the client  */
evhttp_send_reply(req, HTTP_OK, "OK", buf);
//evbuffer_add_printf(buf, "%s", "HTTPSQS_AUTH_FAILED");
/*  Release the memory  */
evbuffer_free(buf);
fprintf(stderr,"Send \n");
}

编译:(编译时把libevent的类库中的.so文件和.h文件连接
进来)

Sh代码
  1. gcchttp.c-L/usr/local/libevent-2.0.12-stable/lib/-levent-I/usr/local/libevent-2.0.12-stable/include/
gcc http.c -L/usr/local/libevent-2.0.12-stable/lib/ -levent -I/usr/local/libevent-2.0.12-stable/include/

测试

在服务器端,执行编译后的文件a.out

Java代码
  1. ./a.out
./a.out

客户端进行访问(也可以使用浏览器访问,但是要打开端口号2345——vi /etc/sysconfig/iptables)

Java代码
  1. [www@zhoubcdata]$Snbsp;curlhttp://127.0.0.1:2345
[www@zhoubc data]$ curl http://127.0.0.1:2345

此时再看服务端,变成如下状态

Java代码
  1. [www@zhoubcqueue]$Snbsp;./a.out
  2. Send
[www@zhoubc queue]$ ./a.out
Send 

2.处理http请求,重写htt_handle方法

C代码
  1. voidhttp_handle(structevhttp_request*req,void*arg){
  2. structevbuffer*buf;
  3. buf=evbuffer_new();
  4. /*AnalysttheURI*/
  5. char*decode_uri=strdup((char*)evhttp_request_uri(req));
  6. structevkeyvalqhttp_query;
  7. evhttp_parse_query(decode_uri,&http_query);
  8. free(decode_uri);
  9. /*URIParameter*/
  10. constchar*http_input_opt=evhttp_find_header(&http_query,"opt");/*OperationType*/
  11. constchar*http_input_name=evhttp_find_header(&http_query,"name");/*QueueName*/
  12. constchar*http_input_data=evhttp_find_header(&http_query,"data");/*DataWithGET*/
  13. /*header*/
  14. evhttp_add_header(req->output_headers,"Content-Type","text/plain");
  15. evhttp_add_header(req->output_headers,"Connection","keep-alive");
  16. evhttp_add_header(req->output_headers,"Cache-Control","no-cache");
  17. evhttp_add_header(req->output_headers,"author","Dennis.ZRitchie");
  18. if(http_input_opt!=NULL&&http_input_name!=NULL&&strlen(http_input_name)<300){
  19. /*GETMethod,OUTTheQueue*/
  20. if(strcmp(http_input_opt,"put")==0){
  21. intbuffer_data_len=EVBUFFER_LENGTH(req->input_buffer);
  22. if(buffer_data_len>0){/*POSTMETHOD*/
  23. char*input_value_data=EVBUFFER_DATA(req->input_buffer);/*SubmitedData*/
  24. fprintf(stderr,"%s\n",input_value_data);
  25. }elseif(http_input_data!=NULL){
  26. fprintf(stderr,"%s\n",http_input_data);
  27. }
  28. }elseif(strcmp(http_input_opt,"get")==0){
  29. }
  30. }
  31. /*Responsetheclient*/
  32. evhttp_send_reply(req,HTTP_OK,"OK",buf);
  33. //evbuffer_add_printf(buf,"%s","HTTPSQS_AUTH_FAILED");
  34. /*Releasethememory*/
  35. evhttp_clear_headers(&http_query);
  36. evbuffer_free(buf);
  37. }
void http_handle(struct evhttp_request *req, void *arg){
struct evbuffer *buf;
buf = evbuffer_new();
/*  Analyst the URI  */
char *decode_uri = strdup((char*) evhttp_request_uri(req));
struct evkeyvalq http_query;
evhttp_parse_query(decode_uri, &http_query);
free(decode_uri);
/*  URI Parameter  */
const char *http_input_opt = evhttp_find_header (&http_query, "opt"); /* Operation Type */
const char *http_input_name = evhttp_find_header (&http_query, "name"); /* Queue Name */
const char *http_input_data = evhttp_find_header (&http_query, "data"); /* Data With GET */
/*  header  */
evhttp_add_header(req->output_headers, "Content-Type", "text/plain");
evhttp_add_header(req->output_headers, "Connection", "keep-alive");
evhttp_add_header(req->output_headers, "Cache-Control", "no-cache");
evhttp_add_header(req->output_headers, "author", "Dennis .Z Ritchie");
if(http_input_opt != NULL && http_input_name != NULL && strlen(http_input_name) < 300){
/*  GET Method,OUT The Queue  */
if(strcmp(http_input_opt,"put") == 0){
int buffer_data_len = EVBUFFER_LENGTH(req->input_buffer);
if(buffer_data_len > 0){ /* POST METHOD */
char *input_value_data = EVBUFFER_DATA(req->input_buffer); /* Submited Data */
fprintf(stderr,"%s \n",input_value_data);
}else if(http_input_data != NULL){
fprintf(stderr,"%s \n",http_input_data);
}
}else if(strcmp(http_input_opt,"get") == 0){
}
}
/*  Response the client  */
evhttp_send_reply(req, HTTP_OK, "OK", buf);
//evbuffer_add_printf(buf, "%s", "HTTPSQS_AUTH_FAILED");
/*  Release the memory  */
evhttp_clear_headers(&http_query);
evbuffer_free(buf);
}
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。