epoll+反应堆模式

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define MAX_EVENTS 500
#define BACKLOG 10

struct st_myevents
{
	int fd;
	void (*call_back)(int fd, int events, void *arg);
	int events;
	void *arg;
	int status;
	long last_active;
	int len;
	char buf[1024];
};

struct st_myevents myEvents[MAX_EVENTS+1]; //myEvent[MAX_EVENTS] use for listenfd
int g_epfd;

int setnonblock(int fd);
void InitListenSocket(int port);
void Accept_cb(int fd, int events, void *arg);
void EventSet(int fd, struct st_myevents *ev, void (*call_back)(int , int , void *), void *arg );
void EventAdd(int epfd, int events, struct st_myevents *ev);
void EventDel(int epfd, struct st_myevents *ev);
void RecvData(int fd, int events, void  *arg);
void SendData(int fd, int events, void *arg);

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

	if(argc < 2)
	{
		perror("no input port");
		return -1;
	}
	int i=0;
	int dua=0;
	long now;
	int port = atoi(argv[1]);
	struct epoll_event events[MAX_EVENTS];
	g_epfd = epoll_create(MAX_EVENTS);
	if(g_epfd <0)
	{
		perror("g_epfd error");
		return -1;
	}
	InitListenSocket(port);
	
	do
	{
	    now = time(NULL);
		for(i=0;i 60)
			{
				printf("timeout [%d]\n", myEvents[i].fd);
				close(myEvents[i].fd);
                EventDel(g_epfd, &myEvents[i]);
			}
		}	
		int fds = epoll_wait(g_epfd, events, MAX_EVENTS, 500);
		if(fds < 0)
		{
			perror("epoll_wait error");
			break;
		}
		for(i=0; i< fds; ++i)
		{
			struct st_myevents *ev = (struct st_myevents*)events[i].data.ptr;
			if((events[i].events&EPOLLIN)&&(ev->events&EPOLLIN)) // read event
	            ev->call_back(ev->fd, events[i].events, ev->arg);
	        if((events[i].events&EPOLLOUT)&&(ev->events&EPOLLOUT)) // write event 
	            ev->call_back(ev->fd, events[i].events, ev->arg);
		}
		
	}while(1);

	close(g_epfd);
	for(i=0;i 0)
		{
			close(myEvents[i].fd);
			free(myEvents[i].buf);
			myEvents[i].arg = NULL;
		}

	}
    return 0;
}
int setnonblock(int fd)
{
    if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0)|O_NONBLOCK) == -1) {
        return -1;
    }
    return 0;
}

void InitListenSocket(int port)
{
	int listenfd = socket(AF_INET, SOCK_STREAM, 0);
	setnonblock(listenfd);
	printf("serve listen fd=%d\n", listenfd);
	EventSet(listenfd, &myEvents[MAX_EVENTS], Accept_cb, &myEvents[MAX_EVENTS]);
	EventAdd(g_epfd, EPOLLIN|EPOLLET, &myEvents[MAX_EVENTS]);
	
	struct sockaddr_in sin;
	bzero(&sin, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_port = htons(port);
	int opt = 1;
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	
	if(bind(listenfd,(struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		perror("bind error");
		return;
	}
	if(listen(listenfd, BACKLOG) <0)
	{
		perror("listen error");
		return ;
	}
	
}

void EventSet(int fd, struct st_myevents *ev, void (*call_back)(int , int , void *arg), void *arg)
{
	ev->fd = fd;
	ev->call_back = call_back;
	ev->events = 0;
	ev->arg = arg;
	ev->status = 0;
	ev->last_active = time(NULL);
}

void EventAdd(int epfd, int events, struct st_myevents *ev)
{
	struct epoll_event ep;
	memset(&ep, 0, sizeof(ep));
	int op;
	ep.data.ptr = ev;
	ev->events = events;
	ep.events = events;
	
	if(ev->status == 1)
	{
		op = EPOLL_CTL_MOD;
	}
	else
	{
		op = EPOLL_CTL_ADD;
		ev->status = 1;
	}
	if(epoll_ctl(epfd, op, ev->fd, &ep) < 0)
	{
		perror("event add failed");
		return;
	}
	else
	{
		printf("event add ok[fd = %d]\n", ev->fd);
	}
}

void EventDel(int epfd, struct st_myevents *ev)
{
	struct epoll_event ep;
	memset(&ep, 0, sizeof(ep));
	if(ev->status != 1) return;  
	ep.data.ptr = ev;  
	ev->status = 0;  
	epoll_ctl(g_epfd, EPOLL_CTL_DEL, ev->fd, &ep);  
}

void Accept_cb(int fd, int events, void *arg)
{
	struct sockaddr_in cin;
	socklen_t len = sizeof(struct sockaddr_in);
	int cfd;
	int i;
	if((cfd = accept(fd, (struct sockaddr*)&cin, &len)) < 0)
	{
		perror("accept error");
		return;
	}
	printf("new conneciton[%s:%d]\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
	do{
		for(i=0;ibuf, sizeof(ev->buf)-1, 0);
	EventDel(g_epfd, ev);
	if(len < 0)
	{
		close(fd);
		printf("client fail connetion [%d]\n", ev->fd);
	}
	if(len > 0)
	{
		ev->len = len;
		ev->buf[len] = '\0';
		EventSet(fd,ev, (void*)SendData, ev);
		EventAdd(g_epfd, EPOLLOUT|EPOLLET, ev);
		printf("recv data: %s\n", ev->buf);
	}
	
}

void SendData(int fd, int events, void *arg)
{
	struct st_myevents *ev = (struct st_myevents*)arg;
	int len;
	len = send(fd, ev->buf, ev->len, 0);
	EventDel(g_epfd, ev);
	if(len < 0)
	{
		close(fd);
		printf("client fail connetion [%d]\n", ev->fd);
	}
	if(len > 0)
	{
		ev->len = 0;
		bzero(ev->buf, sizeof(ev->buf));
		EventSet(fd,ev,(void*)RecvData, ev);
		EventAdd(g_epfd, EPOLLIN|EPOLLET, ev);		
	}
}










你可能感兴趣的:(c/c++,linux学习,socket,c)