#include<unistd.h>
#include<errno.h>
#include<sys/epoll.h>
#include<fcntl.h>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<sys/socket.h>
#include<arpa/inet.h>
using namespace std;
#define EVENT_SIZE 1024
struct Myevent{
int fd;
int status;
void* args;
int events;
void (*callback)(int fd,int events,void* arg);
char buf[BUFSIZ];
int len;
long last_active;
};
int g_efd;
Myevent g_event[EVENT_SIZE+1];
void recvdata(int,int,void*);
void senddata(int,int,void*);
void eventset(Myevent* ev,int fd,void (*callback)(int,int,void*),void* arg){
ev->fd=fd;
ev->status=0;
ev->args=arg;
ev->events=0;
ev->callback=callback;
//memset(ev->buf,0,BUFSIZ);
ev->last_active=time(NULL);
}
void eventadd(int fd,int event,Myevent* ev){
int op;
epoll_event epv;
epv.events=ev->events=event;
epv.data.ptr=ev;
if(ev->status==0){
op=EPOLL_CTL_ADD;
ev->status=1;
}
else{
return;
}
if(epoll_ctl(g_efd,op,fd,&epv)<0){
cout<<"event add error"<<endl;
return;
}
else{
cout<<"event add ok"<<endl;
}
}
void eventdel(int efd,Myevent* event){
int op;
epoll_event epv;
if(event->status==0){
return;
}
else if(event->status==1){
event->status=0;
op=EPOLL_CTL_DEL;
}
event->status=0;
epv.data.ptr=nullptr;
if(epoll_ctl(efd,op,event->fd,&epv)<0){
cout<<"event del error"<<endl;
return;
}
else{
cout<<"event del ok"<<endl;
}
}
void senddata(int fd,int event,void* arg){
Myevent* ev=(Myevent*)arg;
int ret=send(fd,ev->buf,ev->len,0);
eventdel(g_efd,ev);
if(ret>0){
eventset(ev,fd,recvdata,ev);
eventadd(fd,EPOLLIN,ev);
}
else{
close(fd);
cerr<<"send erro"<<endl;
}
}
void recvdata(int fd,int event,void* arg){
Myevent* ev=(Myevent*)arg;
int ret=recv(fd,ev->buf,BUFSIZ,0);
eventdel(g_efd,ev);
if(ret==0){
close(fd);
cout<<"a client close connect"<<endl;
}
else if(ret>0){
ev->len=ret;
for(int i=0;i<ret;i++){
ev->buf[i]=::toupper(ev->buf[i]);
}
eventset(ev,fd,senddata,ev);
eventadd(fd,EPOLLOUT,ev);
}
else{
cerr<<errno<<endl;
}
return;
}
void acceptconn(int lfd,int event,void* arg){
sockaddr_in cliadd;
socklen_t clilen=sizeof(cliadd);
int cfd=accept(lfd,(sockaddr*)&cliadd,&clilen);
char ipbuf[BUFSIZ];
cout<<"ip:"<<inet_ntop(AF_INET,&cliadd.sin_addr,ipbuf,BUFSIZ)<<" port:"<<ntohs(cliadd.sin_port)<<" connected!"<<endl;
int i;
for(i=0;i<EVENT_SIZE;i++){
if(g_event[i].status==0){
break;
}
}
if(i==EVENT_SIZE){
cout<<"the num of client is full"<<endl;
return;
}
int flag=fcntl(cfd,F_GETFL);
flag|= O_NONBLOCK;
fcntl(cfd,F_SETFL,flag);
eventset(&g_event[i],cfd,recvdata,&g_event[i]);
eventadd(cfd,EPOLLIN,&g_event[i]);
}
void init_listen_socket(int port){
int lfd=socket(AF_INET,SOCK_STREAM,0);
fcntl(lfd,F_SETFL,O_NONBLOCK);
sockaddr_in saddr;
saddr.sin_family=AF_INET;
saddr.sin_port=htons(port);
saddr.sin_addr.s_addr=htonl(INADDR_ANY);
int ret=bind(lfd,(sockaddr*)&saddr,sizeof(saddr));
if(ret<0){
cerr<<"bind error";
}
listen(lfd,1024);
eventset(&g_event[EVENT_SIZE],lfd,acceptconn,&g_event[EVENT_SIZE]);
eventadd(lfd,EPOLLIN,&g_event[EVENT_SIZE]);
return;
}
int main(){
g_efd=epoll_create(EVENT_SIZE+1);
epoll_event events[EVENT_SIZE+1];
init_listen_socket(1998);
while(1){
int ret=epoll_wait(g_efd,events,EVENT_SIZE,-1);
if(ret<0){
cerr<<"epoll_wait error";
}
for(int i=0;i<ret;i++){
Myevent* myeve=(Myevent*)events[i].data.ptr;
if(myeve->events&EPOLLIN){
myeve->callback(myeve->fd,myeve->events,myeve);
continue;
}
if(myeve->events&EPOLLOUT){
myeve->callback(myeve->fd,myeve->events,myeve);
}
}
}
return 1;
}
linux epoll reactor的实现
最新推荐文章于 2024-06-14 14:37:55 发布