libevent服务器页面显示,回显服务器--libevent的使用

1,要使用libevent首先需要安装了,我选着的1.4稳定版本的了,安装过程就是常用linux安装的3步而已

2,在使用libevent之前,了解一下常用的并发服务器的模型还是有必要的基于事件触发的库,常见多线程与并发服务器设计方案举例

3,代码+解释

/*

* Compile with:

* cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define PORT 54321

#define BACKLOG 20

#define MEM_SIZE 1024

struct event_base* base; /*其实就是reactor(反应堆),可以形象的比喻为一个总管理,管理所有提供服务的服务者*/

struct sock_ev {

struct event* read_ev;

struct event* write_ev;

char* buffer;

};

//这是为了能够完全整体的释放内存,以前是这样写的,//如果客户端关闭size==0时候,write_ev,没有得到释放,导致内存泄漏,其实我觉得不用这样封装结构体也可以的,但是封装结构体过后感觉更加面向对象的了的感觉

//void on_read(int sock,short event,void* arg){

//struct event* write_ev;

// int size;

// char* buffer = (char*)malloc(MEM_SIZE);

// bzero(buffer,MEM_SIZE);

// size = recv(sock,buffer,MEM_SIZE,0);

// printf("receive data:%s,size:%d\n",size);

// if (size == 0) {

// event_del((struct event*)arg);

// free((struct event*)arg);

// close(sock);

// return;

//

//}

// write_ev = (struct event*) malloc(sizeof(struct event));;

// event_set(write_ev,sock,EV_WRITE,on_write,buffer);

// event_base_set(base,write_ev);

// event_add(write_ev,NULL);

//}

void release_sock_event(struct sock_ev* ev)

{

event_del(ev->read_ev);

free(ev->read_ev);

free(ev->write_ev);

free(ev->buffer);

free(ev);

}

void on_write(int sock,void* arg)

{

char* buffer = (char*)arg;

send(sock,strlen(buffer),0);

//注意这里需要释放,是在on_read里面malloc的

free(buffer);

}

void on_read(int sock,void* arg)

{

int size;

struct sock_ev* ev = (struct sock_ev*)arg;

ev->buffer = (char*)malloc(MEM_SIZE);

bzero(ev->buffer,MEM_SIZE);

size = recv(sock,ev->buffer,0);

printf("receive data:%s,size);

//当从socket读返回0标志对方已经关闭了连接,因此这个时候就没必要继续监听该套接口上的事件,

//由于EV_READ在on_accept函数里是用EV_PERSIST(持久)参数注册的,因此要显示的调用event_del函数取消对该事件的监听。

if (size == 0) {

release_sock_event(ev);

close(sock);

return;

}

event_set(ev->write_ev,ev->buffer);

event_base_set(base,ev->write_ev);

event_add(ev->write_ev,NULL);

}

void on_accept(int sock,void* arg)

{

struct sockaddr_in cli_addr;

int newfd,sin_size;

//这里必须要malloc,因为这个事件最后是要base里面的,如果是栈中分配,这个函数执行接受过后,变量的值被回收过后,在"后面"工作的base,将对一个空的操作,那样会crash

struct sock_ev* ev = (struct sock_ev*)malloc(sizeof(struct sock_ev));

ev->read_ev = (struct event*)malloc(sizeof(struct event));

ev->write_ev = (struct event*)malloc(sizeof(struct event));

sin_size = sizeof(struct sockaddr_in);

newfd = accept(sock,(struct sockaddr*)&cli_addr,&sin_size);

//这里就是,监听这个sock,是否是可读,如果可以折触发on_read函数了,当然这里的event_set函数是系统补推荐的,建议使用event_assign函数具体可以看文档

event_set(ev->read_ev,newfd,EV_READ | EV_PERSIST,on_read,ev);

event_base_set(base,ev->read_ev);

event_add(ev->read_ev,NULL);

}

int main(int argc,char* argv[])

{

struct sockaddr_in my_addr;

int sock;

sock = socket(AF_INET,SOCK_STREAM,0);

int yes = 1;

//这是是需要注意一下,我们在编程的时候,有时候不小心我们使用的文件句柄,//资源没有释放,而程序有挂了当我们再次使用的时候,就会出线xxxx被用,这里SO_REUSEADDR,就是让他可以重复利用,具体的看以参考

setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int));

//下面这几行就是长用的步骤啦

memset(&my_addr,sizeof(my_addr));

my_addr.sin_family = AF_INET;

my_addr.sin_port = htons(PORT);

my_addr.sin_addr.s_addr = INADDR_ANY;

bind(sock,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));

listen(sock,BACKLOG);

struct event listen_ev; /*它就是直接提供服务的,它呗 base管理*/

base = event_base_new();

//将我们监听的sock,绑定在listen_ev,即使让listen_ev帮我们管理,我们之处理,请求的到来,请求到来了将触发on_accept函数

event_set(&listen_ev,on_accept,NULL);

event_base_set(base,&listen_ev);

event_add(&listen_ev,NULL);

//循环调用,就像服务器要一直运行吧,一旦有新的请求过来或者请求的I/O时候会调用处理

event_base_dispatch(base);

return 0;

}

总结

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值