多线程代理服务器version2
#include "stdio.h" #include "stdlib.h" #include "sys/socket.h" #include "netinet/in.h" #include "netinet/tcp.h" #include "arpa/inet.h" #include "string.h" #include <errno.h> #include "sys/time.h" #include "sys/times.h" #include <unistd.h> #include "sys/types.h" #include "sys/stropts.h" #include <signal.h> #include <time.h> #include <pthread.h> #include "sockopt.h" #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #define msglen 1500 typedef struct map { int serverfd; int clientfd; }map; int bindlisten(); int clientconn(); void DLog(); closemap(int sockfd,fd_set fdset,struct map *a); #define MAX_MSG_LEN (1024+1) #define MAXNUM 65535 void *m_cbf(void *__args); fd_set ReadData (int fd,fd_set fdset,struct map *a); int temp; #define K_MILLISECPERSEC 1000 #define MSECWAITTIME 10000 #define SETTIMEOUT(x) (x).tv_sec = (MSECWAITTIME/K_MILLISECPERSEC),(x).tv_usec=(MSECWAITTIME%K_MILLISECPERSEC)*K_MILLISECPERSEC main () { struct sockaddr_in tcpaddr; int retVal,ret; char line[msglen]={0}; int tcpaddr_len; int lstnScktNum; int count=0,errno; int max_fd,client; int fd,serverfd; char *str; fd_set fdset; pthread_t m_threadId[MAXNUM]; //for broken pipe; which write twice for descript,one is rst ,another is broken pipe signal (SIGPIPE,SIG_IGN); serverfd=bindlisten(); if (serverfd==-1) { printf("line62:bind & listen fail\n"); return -1 ; } FD_ZERO(&fdset); FD_SET(serverfd, &fdset); max_fd = serverfd; //first select then accept //socket and select are event trigger while (1) { fd_set oset; //select timeout all fd reset to 0, because we need check fd ,so we need recover the save value oset = fdset; struct timeval timeout; SETTIMEOUT(timeout); //select set noblock ,is set for timeout //select test two read fd,one is from user, one is from proxy count=select(max_fd+1,&oset,NULL,NULL,&timeout); if(count > 0){ for(fd = 0; fd <= max_fd; fd++){ if(FD_ISSET(fd, &oset)){ //only for listen fd //This is a new connection. tcpaddr_len = sizeof(tcpaddr); //the accept tcpaddr is diffrent from bind. it get cient ip with & //the bind tcpaddr is server address client =accept(fd, (struct sockaddr *)(&tcpaddr), &tcpaddr_len); str=inet_ntoa(tcpaddr.sin_addr); if(client > 0){ printf("Accept a new client: %d\n", client); #if 1 ret=setTcpScktOptions(client); if (ret <0) { printf("line88 ret=%d\n",ret); return -1; } #endif retVal=pthread_create(&m_threadId[client],NULL,m_cbf,(void *)client); if (retVal!=0) { printf ("create thread failt\n"); //only one thread don;t should //affect other thread run well continue; } }else{ //debug scoket error perror("accept()"); } } } } else if (count ==0) { continue; }else { perror("line192\n"); printf("error:fd=%d\n",fd); break; } } for (fd=0;fd<=max_fd;fd++) { if(FD_ISSET(fd, &fdset)){ close (fd); } } } int bindlisten() { struct sockaddr_in tcpaddr; struct in_addr intfIpAddr; int tcpaddr_len; int sockfd; int client; int port=9100; int bReuseaddr=1; int retVal; int ret; int buf,optlen; int on,errno; memset( &tcpaddr, 0, sizeof(tcpaddr) ); if ( (sockfd= socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { printf ("socket create fail\n"); return -1; } // 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); on=1; errno=0; ret=setTcpScktOptions(sockfd); if (ret <0) printf("line253 setsockopt fail:ret=%d\n",ret); // make bind call if ((retVal = bind(sockfd, (struct sockaddr *)(&tcpaddr), sizeof(tcpaddr)))< 0 ) { printf("bind() call failed. Error: %d, %s,port: %d\n ", errno, ( strerror(errno) ), port); } //listen have 5 queue if (listen(sockfd, 5) < 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)); //135.245.1.1 is default proxy ip strcpy(ipHost, "135.245.1.1"); /* 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 1 ret=setTcpScktOptions(sockfd); if (ret<0) { printf("line257:ret=%d\n",ret); return -1; } #endif //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; } closemap (int fd, fd_set fdset,struct map *a) { //The socket is wrong or closed. close(fd); FD_CLR(fd, &fdset); printf("close %d\n",fd); //remove the socketfd //don;t judge from user or proxy ,set all kind to 0 //one sockfd close ,peer sockfd close // if (a[fd]!=0) { if (fd==a->serverfd) { temp=a->clientfd; close(temp); printf("client close %d\n",temp); FD_CLR(a->clientfd, &fdset); free(a); else if (fd==a->clientfd) { temp=a->serverfd; close(temp); printf("server close %d\n",temp); FD_CLR(temp, &fdset); free(a); } pthread_exit(NULL); } void *m_cbf(void *__args) { int connfd,max_fd=0; int count; fd_set pset; char line[msglen]; int retVal,ret; int clientfd; int fd; struct map *a; //it can been free in child function ,but child function is _p ,it is a copy, it can;t remove this one, so it can become a laji a=(struct map *)malloc(sizeof(map)); connfd=(int)__args; FD_ZERO(&pset); //put connfd and create connect to proxy and make map FD_SET(connfd, &pset); if(connfd> max_fd) max_fd = connfd; clientfd=clientconn(); if (clientfd==-1) { printf("line398:clientfd fail\n"); return 0; } printf("create a new connect to proxy: %d\n", clientfd); ret=setTcpScktOptions(clientfd); if(ret<0) { printf("line405:ret=%d\n",ret); } //put connect to proxy fd into fd_set FD_SET(clientfd, &pset); if(clientfd > max_fd) max_fd = clientfd; //map user and proxy socket //a keep proxy,b keep user a->serverfd=connfd; a->clientfd=clientfd; // a[connfd]=clientfd; // b[clientfd]=connfd; while (1) { fd_set oset; //select timeout all fd reset to 0, because we need check fd ,so we need recover the save value //pset bit set 1 oset = pset; struct timeval timeout; SETTIMEOUT(timeout); switch ((count=select(max_fd+1,&oset,NULL,NULL,&timeout))) { case 0://timeout continue; case -1://error if (errno ==EINTR) { count=0; break; } printf("select ERROR:%d,%s\n",errno,strerror(errno)); break; default://data found break; } if (count <0) continue; //becasue the fd all read,not one accept ,the other read.we don;t need judge. //it may come from proxy or user,we need tranverse for(fd = 0; fd <= max_fd; fd++){ if(FD_ISSET(fd, &oset)) { //oset=ReadData(fd,oset); pset=ReadData(fd,pset,a); break; } } } } fd_set ReadData (int fd,fd_set oset,struct map *a) { char line[msglen]; int ret ,retVal; int fdmap; memset(line,0x00,msglen); //msglen is what i read, retVal is the real i read success ,they are not the same retVal = read(fd, line, msglen); if(retVal <= 0){ //EINTR means don;t red out data,but don;t close the fd if (errno==EINTR) return ; else closemap(fd,oset,a); } else{ if (fd==a->serverfd) { fdmap=a->clientfd; // if is in a, it come from proxy,so write to user //forward message to ;ucent printf("Write 1:from %d to %d\n",fd, fdmap); ret=write(fdmap,line,retVal); if (ret <=0) { if (errno==EINTR) return; else { perror("write() 1"); closemap(fdmap,oset,a); } } else { printf("write to proxy\n"); } } else if (fd==a->clientfd) { fdmap=a->serverfd; //is in b, it come from user //forward message to user printf("Write 2 from %d to %d\n",fd, fdmap); ret=write(fdmap,line,retVal); if (ret <0) { if (errno==EINTR) return; else { perror("write() 2"); closemap(fdmap,oset,a); } } else { printf("write to user\n"); } } } return oset; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。