天天看点

epoll编程

实例编程后续完善各种问题处理,以及定时处理等等:

myepoll.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <signal.h>

#include <sys/wait.h>
#include <string.h>
#include <errno.h>

#define MAXEPOLLFD	1000
#define PORT				6785
#define PIDNUM			20
int Port = PORT;
int iGetsocknum=0;
int iListenfd,iEpollfd;
struct epoll_event events[MAXEPOLLFD];  
struct epoll_event ev;
pid_t forkpid[PIDNUM];

extern void mydaemon();
extern int iGLoop;
extern void iLoopSet();
extern void SetNoBlock(int fd,int type);
extern int Setsockopt(int fd,int type );
extern void Mylisten(int fd,int listennum);
extern int Mybind(int fd,int type);
typedef void ( * sighandler_t) (int);
extern sighandler_t SetSigHandler(int sigtype,sighandler_t handler);
extern int GetSocket(int type);

void KillChild()
{
	for ( int i=0;i<PIDNUM;i++ )
	{
		kill(forkpid[i],SIGUSR1);
	}
}
int GetEpoll(int size){
	return epoll_create(size);
}

int EpollSet(int epollfd,int fd,int type ,int type1){
	
	struct epoll_event event;
	int epolltype=0,iRet=0;
	
	memset((char *)&event,0x00,sizeof(event));
	
	event.data.fd = fd;
	
	
	switch( type ){
		case 0:
			epolltype = EPOLL_CTL_MOD;
			break;
		case 1:
			epolltype = EPOLL_CTL_ADD;
			break;
		case 3:
			epolltype = EPOLL_CTL_DEL;
		default:
			epolltype = EPOLL_CTL_ADD;
			break;
	}
	switch( type1 ){
		case 0:
			event.events = EPOLLIN|EPOLLET;
			break;
		case 1:
			event.events = EPOLLOUT|EPOLLET;
			break;
		default:
			event.events = EPOLLIN|EPOLLET;
			break;
	}
	
	iRet  = epoll_ctl(epollfd,epolltype,fd,&event);
	if ( iRet == -1 )
	{
		return -1;		
	}
	return 0;
}

int EpollWait(){
	int fd=0;
	fd = epoll_wait(iEpollfd, events, MAXEPOLLFD, 5000);
	if ( fd == -1 )
	{
//		DeBugLog();	
	}
	return fd;
}

int InitListenSockt(int port)
{
		int iRet=0;
		socklen_t socklen;
		struct sockaddr_in stServ;
		socklen = sizeof( struct sockaddr_in  );
		iListenfd = GetSocket(0);
		if ( iListenfd == -1 )
		{
			return -1;	
		}
		
		memset((char *)&stServ,0x00,sizeof(stServ));
		
		if ( Mybind(iListenfd,0 ) == -1 )
		{
				return -1;
		}
		
		Mylisten(iListenfd,200);
		
		if (Setsockopt(iListenfd,0) == -1 )
		{
				return -1;
		}
		return iListenfd;
}

void Woker()
{
		int fd=0;
		int connectfd=0;
		char sReadBuf[1024];
		char sWriteBuf[1024];
		int iReadnum=0;
		int iWriteNum=0;
		
		iEpollfd=GetEpoll(MAXEPOLLFD);
		
		
		EpollSet(iEpollfd,iListenfd,1,0);
		SetSigHandler(SIGUSR1,iLoopSet);
		memset(sReadBuf,0x00,sizeof(sReadBuf));
		memset(sWriteBuf,0x00,sizeof(sWriteBuf));
		
		while(iGLoop)
		{
			
			fd= EpollWait();
			for ( int i=0;i<fd;i++)
			{
					if ( events[i].data.fd == iListenfd )
					{
						connectfd = accept(events[i].data.fd ,NULL, NULL);
						if ( connectfd < 0 )
						{
	//						DeBugLog();	
						}
						SetNoBlock(connectfd,0);
						EpollSet(iEpollfd,connectfd,1,0);
					}
					else
					{
						if ( events[i].events&EPOLLIN )	
						{
							if ( events[i].data.fd < 0 )
								continue;
							iReadnum = read( events[i].data.fd,sReadBuf,1024 );
							
							if ( iReadnum == 0 )
							{
									
										EpollSet(iEpollfd,events[i].data.fd,3,0);
										events[i].data.fd = -1;
										fprintf(stdout,"error 1 %s\n",sReadBuf);
										close(events[i].data.fd);	
									
							}
							if ( iReadnum < 0 )
							{
								if ( errno == EAGAIN || errno == EWOULDBLOCK || errno==EINTR )	
												continue;
											else
											{
													EpollSet(iEpollfd,events[i].data.fd,3,0);
													events[i].data.fd = -1;
													fprintf(stdout,"error 2 get %s\n",sReadBuf);
													close(events[i].data.fd);	
											}
							}
							fprintf(stdout,"get: %s \n",sReadBuf);
							EpollSet(iEpollfd,events[i].data.fd,0,1);
							
						}
						else
						{
								if ( events[i].events&EPOLLOUT )
								{
										if ( events[i].data.fd < 0 )
											continue;
										memset(sWriteBuf,0x00,sizeof(sWriteBuf));
										sprintf(sWriteBuf,"send: server fd %d num %d \n",events[i].data.fd,iGetsocknum);
										//iWriteNum = wirte( events[i].data.fd,sWriteBuf,30 );	
										iWriteNum = write( events[i].data.fd,sWriteBuf,30 );
										if ( iWriteNum == 0 )
										{
													
											  EpollSet(iEpollfd,events[i].data.fd,3,0);
												events[i].data.fd = -1;
												fprintf(stdout,"error 1 write %s\n",sReadBuf);
												close(events[i].data.fd);	
											  
										}
										if ( iWriteNum < 0 )
										{
											if ( errno == EAGAIN || errno == EWOULDBLOCK )	
												continue;
											else
											{
													EpollSet(iEpollfd,events[i].data.fd,3,0);
													events[i].data.fd = -1;
													fprintf(stdout," error 2 write %s\n",sReadBuf);
													close(events[i].data.fd);	
											}
										}
										//fprintf(stdout,"%s %s\n",sWriteBuf,strerror(errno));
								}
								EpollSet(iEpollfd,events[i].data.fd,0,0);
						}
					}
			}
			iGetsocknum++;
		}
		
}

int main(int argc,char **argv){
	
	
	mydaemon();
	InitListenSockt(PORT);
	
	
	for ( int i=0;i<PIDNUM;i++)
	{
			forkpid[i] = fork();
			if ( forkpid[i] ==-1 )
			{
				exit(-1);	
			}
			if ( forkpid[i] == 0 )
			{
				Woker();	
			}
	}
	SetSigHandler(SIGINT,KillChild);
	for ( int i=0;i<PIDNUM;i++ )
	{
		wait(NULL);
	}
		
}


           

mydaemon.c

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <string.h>

void mydaemon(){
	
	pid_t pid;
	
	pid= fork();
	
	if ( pid > 0 )
	{
		/*父进程退出*/
		exit(0);		
	}
	/*设置进程组识别码方便接收组内进程的信号*/
	setpgrp( );
	/*创建会话,成为会话组长,摆脱控制终端,成为可以打开设备的进程*/
	setsid( );
	/*忽略挂起信号*/
	signal( SIGHUP, SIG_IGN );
	/*重新创建子进程,防止误打开终端设备,fork之后保证子进程不会是会话首进程。*/
  pid = fork( ) ;
	if ( 	pid > 0 )
	{
		exit( 0 );
	}
	/*设置进程掩码,去除继承自父进程的掩码设置*/
	umask( 0 );
	int i = -1;
	//i=getdtablesize();
	/*关闭无用的打开的文件描述符,先获取可打开的最大文件描述符,然后轮询关闭*/
	for ( i;i>=0;i-- )
		( void ) close( i );
		
}
           

lib.c

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/epoll.h>

#define DeBugLog() fprintf(stderr,"%s %d %d: %s\n",__FILE__,__LINE__,__func__,strerror(errno))
typedef void ( * sighandler_t) (int);
int iGLoop=1;
extern int Port;

void iLoopSet()
{
		iGLoop = 0;
}
sighandler_t SetSigHandler(int sigtype,sighandler_t handler){
	return signal(sigtype,handler);
}
void SetNoBlock(int fd,int type){
	
	int iRet=0;
	
	switch( type )
	{
		case 0:
			iRet = fcntl(fd,F_SETFL,O_NONBLOCK);
			break;
		default:
			iRet = fcntl(fd,F_SETFL,O_NONBLOCK);
			break;
	}
	
	if ( iRet == -1 )
	{
			DeBugLog();
	}
	
}




int GetSocket(int type){
	int sockfd;
	switch(  type )
	{
		case 0 :
				sockfd=socket(AF_INET,SOCK_STREAM,0);
				break;
		case 1:
				break;
		case 2:
		default:
				sockfd=socket(AF_INET,SOCK_STREAM,0);
				break;
	}
	if ( sockfd < 0 )
		DeBugLog();
	return sockfd;
}

int Mybind(int fd,int type){
		int iRet=0;
		socklen_t socklen;
		struct sockaddr_in stServ;
		socklen = sizeof( stServ );
		memset((char *)&stServ,0x00,sizeof(stServ));
		switch( type )
		{
			case 0: stServ.sin_family = AF_INET;
							break;
			default:
							break;  
		}
		stServ.sin_addr.s_addr = INADDR_ANY;   
		stServ.sin_port = htons(Port); 
		if ( bind(fd,(struct sockaddr*)&stServ,socklen ) == -1 )
		{
				DeBugLog();
				return -1;
		}
		
}
void Mylisten(int fd,int listennum){
		listen(fd,listennum);
}

int Setsockopt(int fd,int type )
{
	int reuseaddr=1;
	int iRet=0;
	switch( type )
	{
		case 0:
			iRet=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const void *) &reuseaddr, sizeof(int));
			break;	
		case 1:
			iRet=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const void *) &reuseaddr, sizeof(int));
			break;	
		default:
			iRet=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const void *) &reuseaddr, sizeof(int));
			break;	
		
	}
	if ( iRet == -1 )
	{
				DeBugLog();
	}
	return 	iRet;
}