一会要去开会了,等下午或者晚上抽空再说明一下这个基于libevent写的echo服务器
#include <iostream>
#include <event2/listener.h>
#include <arpa/inet.h>
#include <event2/event.h>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <error.h>
#include <sys/socket.h>
using namespace std;
//拔网线的话进不到这个函数中
void client_cb(int client_sock,short which,void* arg)
{
//水平触发,没有处理的话会一直触发事件
//边沿触发,只会触发一次,没有处理,数据就没了,要加while
event* ev = static_cast<event*>(arg);
//判断超时事件
if(which & EV_TIMEOUT){
cout<<"time out"<<endl;
event_free(ev);
close(client_sock);
cout<<"客户端超时"<<endl;
return ;
}
char buff[1024] = {0};
int r = recv(client_sock,buff,sizeof(buff)-1,0);
if(r == 0){//关闭客户端
event_free(ev);
close(client_sock);
return ;
}
buff[r] = '\0';
cout<<"接收到一条消息"<<buff<<endl;
send(client_sock,buff,strlen(buff),0);
}
void listen_cb(int server_sock,short,void* arg)
{
event_base* base = static_cast<event_base*>(arg);
cout << "listen_cb" << endl;
sockaddr_in addr;
socklen_t size = sizeof(addr);
int client = accept(server_sock,(sockaddr*)&addr
,&size);
char ip[16] = { 0 };
evutil_inet_ntop(AF_INET,&addr.sin_addr,ip,sizeof(ip));
cout<<"client ip is"<<ip<<endl;
//客户端读取事件
event* ev = event_new(base,client,
EV_READ | EV_PERSIST,client_cb,
event_self_cbarg());
//event_selef_cbarg()返回当前创建的事件,好直接加载到client_cb
timeval t={10,0};
event_add(ev,&t);
}
int main(int argc,char** argv){
int port = 9996;
if(argc > 1){
port = atoi(argv[1]);
}
//忽略管道信号
if(signal(SIGPIPE,SIG_IGN) == SIG_ERR){
return 1;
}
//创建event的上下文
event_base* base = event_base_new();
if(base){
cout<<"event_base_new successful!"<<endl;
}
else {
cout<<"base failed"<<endl;
return -1;
}
evutil_socket_t sock = socket(AF_INET,SOCK_STREAM,0);
if(sock <=0){
cerr<<"socket failed"<<strerror(errno)<<endl;
return -1;
}
//设置地址复用和非阻塞
evutil_make_listen_socket_reuseable(sock);
evutil_make_socket_nonblocking(sock);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_pton(AF_INET,"127.0.0.1",&addr.sin_addr);
if (bind(sock,(sockaddr*)&addr,sizeof(addr) ) < 0 ) {
cerr<<"bind error"<<strerror(errno)<<endl;
return -1;
}
listen(sock,10);
//接受连接事件
// event *ev = event_new(base,sock,EV_READ |
// EV_PERSIST,listen_cb,base);
//边缘触发
event *ev = event_new(base,sock,EV_READ |
EV_PERSIST | EV_ET,listen_cb,base);
event_add(ev,NULL);
//事件分发处理,事件主循环
event_base_dispatch(base);
close(sock);
if(base)
event_base_free(base);
return 0;
}