上一篇的客户端还是可以使用的哦,所以在这里我就不敲了。
使用监听器的服务器跟上一篇的服务器稍微有一点点的改动(自动bind,listen,自动accept),主要是调用了这个API,上代码前,先来说说这个API
//头文件是<event2/listener.h>
//返回一个监听器
//base是event_base_new的返回值
//cb是一个回调函数 ,函数原型是void cb (struct evconnlistener *listener, evutil_socket_t socketfd, struct sockaddr *addr, int addrlen, void *arg);当客户端connect连接成功时调用
//arg是传递给回调函数cb最后一个形参的值
//flag是一些标志,一般我们写LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC,表示端口可以复用,释放监听器时会自动关闭底层套接字
//backlog是最大未决连接数,说简单点就跟listen函数的第二个参数一样
//addr,addrlen跟bind函数的两个参数是一样的
struct evconnlistener *evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, void *arg, unsigned flags, int backlog,const struct sockaddr *addr, int addrlen);
//说说回调函数cb
//socketfd就是accept产生的socketfd,但是这里的accept底层会自动调用
//addr,addrlen跟accpet后面两个参数是一样的
//arg就是evconnlistener_new_bing传过来的值
void cb(struct evconnlistener *listener, evutil_socket_t socketfd, struct sockaddr *addr, int addrlen, void *arg);
//下面直接上干货
#include<stdlib.h>
#include<stdio.h>
#include<sys/socket.h>#include<sys/types.h>
#include<unistd.h>
#include<event2/event.h>
#include<event2/bufferevent.h>
#include<event2/buffer.h>
#include<event2/listener.h>
static int num=0;
{
char readBuf[4096]={0};
bufferevent_read(buffer,readBuf,sizeof(readBuf));
printf("client%d send:%s",(int)arg,readBuf);
bufferevent_write(buffer,readBuf,sizeof(readBuf));
}
{
if(what&BEV_EVENT_EOF)
{
printf("client%d closed\n",(int)arg);
}
else if(what&BEV_EVENT_ERROR)
{
printf("some other error\n");
}
bufferevent_free(buffer);
}
//当客户端连接成功时候,调用这个函数
void callback_listen(struct evconnlistener *listener, evutil_socket_t socketfd, struct sockaddr *addr, int addrlen, void *arg){
printf("accept produce socketfd is %d\n",socketfd); //socketfd是accept产生的一个套接字,这个套接字是真真用来与客户端进行通信的,不过accept是在底层实现的
struct event_base *base=(struct event_base *)arg; //arg是evconnlistener_new_bind传过来的值,也就是event_base_new的返回值
num++;
printf("client%d connect success......\n",num);
struct bufferevent *buffer=bufferevent_socket_new(base,socketfd,BEV_OPT_CLOSE_ON_FREE);
if(buffer==NULL)
{
perror("bufferevent_socket_new error");
return;
}
bufferevent_setcb(buffer,callback_read,NULL,callback_event,num);
bufferevent_enable(buffer,EV_READ|EV_PERSIST);
}
int main(int argc,char **argv)
{
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(8080);
addr.sin_addr.s_addr=INADDR_ANY;
struct event_base *base=event_base_new();
if(base==NULL)
{
perror("event_base_new error");
return -1;
}
//调用这个函数,会自动bind,listen
//20是传给listen的值
//(struct sockaddr*)&addr,sizeof(addr)是传给bind的值
struct evconnlistener *listener=evconnlistener_new_bind(base,callback_listen,base,LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,20,(struct sockaddr*)&addr,sizeof(addr));
if(listener==NULL)
{
perror("evconnlistener_new error");
event_base_free(base);
return -2;
}
event_base_dispatch(base);
event_base_free(base);
evconnlistener_free(listener);
return 0;
}