linux epoll reactor的实现

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FeiXie8

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值