Click here to Skip to main content
15,886,857 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
i want to do a proxy with epoll. but it fail.
i only open one web , but the accept sockfd constantly increase.
then read fail .
i am very confuse for that

C
#define msglen 1500
#define LISTENQ 20
#define SERV_PORT 7777
#define MAXEVENT 1000

int serverfd,clientfd;
void setNonBlock( int );  
int bindlisten();
int clientconn();

main () {
	struct sockaddr_in  tcpaddr,cliaddr,servaddr;
	int  retVal,errno,count=0;
 	char line[msglen]={0};
	int tcpaddr_len,lstnScktNum;
   	fd_set fdset;
	int  k_milliSecPerSec= 1000,msecWaitTime = 10000;
	struct timeval timeout;
	int max_fd,fd;
	int a[65535]={0},b[65535]={0};
	int listenfd,connfd,sockfd,epfd,nfds;
	ssize_t n;
	socklen_t clilen;
	int i;

	signal (SIGPIPE,SIG_IGN);

	serverfd=bindlisten();
	if (serverfd==-1) {
		printf("line62:bind & listen fail\n");
		return -1 ;
	}
	
	//ev is used to register event , array is usd to send back event which need do with
	struct epoll_event ev, events[20];
	//make fd for doing with accept epoll 
	epfd=epoll_create(MAXEVENT);

	//set and fd which do with event
	ev.data.fd=serverfd;
	ev.events=EPOLLIN|EPOLLET;
	//register epoll event
	epoll_ctl(epfd,EPOLL_CTL_ADD,serverfd,&ev);

	while (1) {
		nfds=epoll_wait(epfd,events,MAXEVENT,0);
		for(i=0; i<nfds;>			fd=events[i].data.fd;
			if (fd==serverfd) 
			{
				clilen=sizeof(cliaddr);
				int connfd =accept(fd, (struct sockaddr *)(&cliaddr), &clilen);
				setNonBlock(connfd);
				if(connfd > 0){
					char *str=inet_ntoa(cliaddr.sin_addr);
					if (ret <0) {
							return -1;
					}
					ev.data.fd=connfd;
					ev.events=EPOLLIN|EPOLLET;
					epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);

					clientfd=clientconn();
					setNonBlock(clientfd);
					if (clientfd==-1) {
							return -1;
					}

					if(ret<0) {
						printf("ret=%d\n",ret);
					}

					ev.data.fd=clientfd;
					ev.events=EPOLLIN|EPOLLET;
					epoll_ctl(epfd,EPOLL_CTL_ADD,clientfd,&ev);
					//map proxy to user
					a[connfd]=clientfd;
					b[clientfd]=connfd;
					
				}
			} 
			else if (events[i].events & EPOLLIN)
			{
				if((sockfd=events[i].data.fd)<0)
					continue;
				//msglen is what i read, retVal is the real i read success ,they are not the same
				retVal = recv(sockfd, line, msglen,MSG_NOSIGNAL);
				if(retVal <= 0){
					if(errno==ECONNRESET) {
						//The socket is wrong or closed.
						close(fd);
						epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev);
						events[i].data.fd=-1;
						//don;t judge from user or proxy ,set all kind to 0
						int temp=a[fd];
						a[fd]=0;
						b[temp]=0;
						temp=b[fd];
						b[fd]=0;
						a[temp]=0;
					} else if(errno!=EAGAIN) {
						perror("line143:read error:");
						return 1; 
					}
				} else {
					if (a[sockfd]!=0) {
						fd=a[sockfd];	
						// if is in a, it come from proxy,so write to user
						//forward message to ;ucent
						int ret=send(fd,line,retVal,MSG_NOSIGNAL);
						if (ret <0 && errno != EAGAIN) {
							perror("write() 1:");
							return 1;
						} else  {
							printf("write to proxy:%d\n",fd);
						}
					} else if (b[sockfd]!=0) {
						fd=b[sockfd];
						//forward message to user
						int ret=send(fd,line,retVal,MSG_NOSIGNAL);
						if (ret <0 && errno != EAGAIN){
							perror("write() 2");
							return 1;
						} else {
								printf("write to user:%d\n",fd);
						}
					}
					memset(line,0x00,msglen);
				}
			} 
			else  {
				fd=events[i].data.fd;
				epoll_ctl(epfd, EPOLL_CTL_DEL,fd, &ev);
				close (fd);
			}
			
    		}
	}

	for(i= 0; i<nfds;>		close(events[nfds].data.fd);
		epoll_ctl(epfd,EPOLL_CTL_DEL,events[nfds].data.fd,&ev);
		events[nfds].data.fd=-1;
	}
}

int bindlisten() {
	struct sockaddr_in    tcpaddr;
	struct in_addr          intfIpAddr;
	int tcpaddr_len;
	int sockfd;
	int port;
	int bReuseaddr=1;
	int retVal;

	memset( &tcpaddr, 0, sizeof(tcpaddr) );
	port=SERV_PORT;

	  if ( (sockfd= socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
		printf ("socket create fail\n");
		return -1;
	}
	  setNonBlock(sockfd);
    // intitalize to hold given restrictions
    tcpaddr.sin_family    = AF_INET;
    tcpaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    tcpaddr.sin_port    = htons(port);

	  tcpaddr_len = sizeof(tcpaddr);

    // make bind call
    if ((retVal = bind(sockfd, (struct sockaddr *)(&tcpaddr), sizeof(tcpaddr)))< 0 ) 
    {
        fprintf(stdout,"bind() call failed. Error: %d, %s,port: %d\n ", errno, ( strerror(errno) ), port);
    }

    int optlen;

    if (listen(sockfd, 20) < 0 )
    {
        printf("Error: Listen socket returned %d %s\n", errno, strerror(errno) );
        return -1;
    }
	return sockfd;
}

int clientconn() {
	struct sockaddr_in tcpaddr;
	char ipHost[10]={0};
	int ipPort=8000;
	int ret;
	int sockfd;
	int bReuseaddr=1;

	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		printf("socket create fail\n");
		return -1;
	}
	/* Connect to the socket */
	memset(&tcpaddr, 0, sizeof(tcpaddr));
	strcpy(ipHost, "127.0.0.0");	
	/* local host, processes must be running on the same machine ... */
	/* intitalize to given address */
	tcpaddr.sin_family	= AF_INET;
	tcpaddr.sin_addr.s_addr = inet_addr((const char *)ipHost);
	tcpaddr.sin_port	= htons(ipPort);

	if (ret<0) {
		return -1;
	}
//basic connect is block, after timeout it return fail
if ((ret = connect(sockfd,(struct sockaddr *)(&tcpaddr),sizeof(tcpaddr))) < 0 ) {
		printf("connect fail,retVal=%d,%s\n",errno,strerror(errno));
		return 1;
}
	return sockfd;

}

void setNonBlock( int sock_fd )  
{  
    int opts;  
    opts = fcntl( sock_fd, F_GETFL );  
    if( opts < 0 )  
    {  
        printf("err:fcntl F_GETFL");  
        exit( 1 );  
    }  
    opts = opts | O_NONBLOCK ;  
    if( fcntl( sock_fd, F_SETFL, opts ) < 0 )  
   {  
        printf("err:fcntl F_SETFL");  
       exit( 1 );  
    }  
}
Posted
Updated 1-Oct-14 3:55am
v2
Comments
CPallini 1-Oct-14 10:01am    
Could please elaborate?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900