c语言中ret IFGO,C语言-使用evhttp实现多线程服务器-Go语言中文社区

#include

#include

#include

#include

#include

#include

#include

#include

#define NTHREADS 5

typedef struct httpd_info{

struct event_base *base;

struct evhttp *httpd;

}httpd_info;

void print_request(struct evhttp_request *request){

switch(request->type)

{

case EVHTTP_REQ_GET:

printf("GET");

break;

case EVHTTP_REQ_POST:

printf("POST");

break;

case EVHTTP_REQ_HEAD:

printf("HEAD");

break;

case EVHTTP_REQ_PUT:

printf("PUT");

break;

case EVHTTP_REQ_DELETE:

printf("DELETE");

break;

case EVHTTP_REQ_OPTIONS:

printf("OPTIONS");

break;

case EVHTTP_REQ_TRACE:

printf("TRACE");

break;

case EVHTTP_REQ_CONNECT:

printf("CONNECT");

break;

case EVHTTP_REQ_PATCH:

printf("PATCH");

break;

default:

printf("UNKNOWN");

}

printf(" %s n",request->uri);

struct evkeyvalq *headers = evhttp_request_get_input_headers(request);

struct evkeyval* kv = headers->tqh_first;

while (kv) {

printf("%s: %sn", kv->key, kv->value);

kv = kv->next.tqe_next;

}

struct evbuffer *buffer=NULL;

buffer=evhttp_request_get_input_buffer(request);

int len=evbuffer_get_length(buffer);

char *data=malloc(len+1);

data[len]=' ';

evbuffer_copyout(buffer,data,len);

printf("n%sn",data);

evhttp_clear_headers(headers);

free(data);

}

void testing(struct evhttp_request * request,void * args){

if (request==NULL)

{

printf("request timeoutn");

return;

}

printf("===THREAD %ld===n",pthread_self());

printf("IP: %s:%dn",request->remote_host,request->remote_port);

print_request(request);

//const char *uri=evhttp_request_get_uri(request);

struct evbuffer *buffer=evbuffer_new();

//evbuffer_add(buffer,"coucou !",8);

evbuffer_add_printf(buffer,"Hello World!");

evhttp_add_header(evhttp_request_get_output_headers(request),"Content-Type","test/plain");

evhttp_send_reply(request,HTTP_OK,"OK",buffer);

evbuffer_free(buffer);

return;

}

void notfound(struct evhttp_request * request,void * args){

evhttp_send_error(request,HTTP_NOTFOUND,"Not Found");

}

void *dispatch(void *args){

struct httpd_info *info=(struct httpd_info *)args;

printf("thread %ld startn",pthread_self());

event_base_dispatch(info->base);

printf("thread %ld donen",pthread_self());

event_base_free(info->base);

evhttp_free(info->httpd);

}

int bind_socket(){

int ret,server_socket,opt=1;

server_socket=socket(AF_INET,SOCK_STREAM|SOCK_NONBLOCK,0);//NOTE 多线程evhttp必须非阻塞

if (server_socket<0)

errx(-1,"ERROR get socket: %dn",server_socket);

setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

struct sockaddr_in addr;

memset(&addr,0,sizeof(addr));

addr.sin_family=AF_INET;

addr.sin_addr.s_addr=INADDR_ANY;

addr.sin_port=htons(8080);

ret=bind(server_socket,(struct sockaddr*)&addr,sizeof(struct sockaddr));

if(ret<0)

errx(-1,"bind errorn");

listen(server_socket,1024);

return server_socket;

}

int main(){

pthread_t ths[NTHREADS];

httpd_info info_arr[NTHREADS],*pinfo;

int i,ret,opt=1,server_socket;

server_socket=bind_socket();

for(i=0;i

{

pinfo=&info_arr[i];

pinfo->base=event_base_new();

if (pinfo->base==NULL)

errx(-1,"ERROR new basen");

pinfo->httpd=evhttp_new(pinfo->base);

if (pinfo->httpd==NULL)

errx(-1,"ERROR new evhttpn");

ret=evhttp_accept_socket(pinfo->httpd,server_socket);

if (ret!=0)

errx(-1,"Error evhttp_accept_socketn");

evhttp_set_cb(pinfo->httpd,"/testing",testing,0);

evhttp_set_gencb(pinfo->httpd,notfound,0);

ret=pthread_create(&ths[i],NULL,dispatch,pinfo);

}

for(i=0;i

{

pthread_join(ths[i],NULL);

}

}

编译gcc test_thread.c -lpthread -levent -o test_thread

多次请求服务器,输出结果如下:

19e87e496f15c3cf97695228905bcc16.png

可见确实有多个线程在处理HTTP请求。

这里有一个坑,如果不是多线程使用evhttp的话,服务器可以正常响应, 如果是多线程的话,必须将socket设为非阻塞的,否则会导致服务端无法响应数据给客户端,而客户端因为等待服务端响应而阻塞住,具体原因未知,但能确定的是tcp连接已经建立。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值