美文网首页
代理服务器select版本

代理服务器select版本

作者: mfdalf | 来源:发表于2020-09-19 10:04 被阅读0次
    4610b912c8fcc3ce41f16515e817e38dd43f20be.jpeg

    落霞与孤鹜齐飞,秋水共长天一色.

    姊妹篇: 代理服务器 poll version: https://blog.csdn.net/fdsafwagdagadg6576/article/details/42872279

    代理服务器多线程版 1:https://blog.csdn.net/fdsafwagdagadg6576/article/details/42872279

    多线程代理服务器version2:https://blog.csdn.net/fdsafwagdagadg6576/article/details/42872371

    #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 "sockopt.h"
    
    #ifndef MSG_NOSIGNAL
    #define MSG_NOSIGNAL 0
    #endif
    #define msglen 1500
    
    int serverfd,clientfd;
    int bindlisten();
    int clientconn();
    void closemap(int sockfd);
    
    int proxy[65535]={0},user[65535]={0};
    int temp;
    fd_set       fdset;
    main () {
            struct sockaddr_in    tcpaddr;
            int            retVal;
            char line[msglen]={0};
            int tcpaddr_len;
            int  lstnScktNum;
            int count=0;
             int  k_milliSecPerSec  = 1000;
             int msecWaitTime = 10000;
            int errno;
            struct timeval timeout;
            int max_fd;
            int fd,fdmap;
            int client;
            char *str;
            int ret;
    
            signal (SIGPIPE,SIG_IGN);
    
            serverfd=bindlisten();
            if (serverfd==-1) {
                printf("bind & listen fail\n");
                return -1 ;
            }
            FD_ZERO(&fdset);
            FD_SET(serverfd, &fdset);
            max_fd = serverfd;
            while (1) {
                fd_set oset;
                //select timeout all fd reset to 0,so we need recover the save value
                oset = fdset;
                // Set the actual value to wait
                msecWaitTime = 10000;
    
                // Set timeout for select call to wtime
                timeout.tv_sec  = msecWaitTime/k_milliSecPerSec;
                timeout.tv_usec = (msecWaitTime%k_milliSecPerSec)*k_milliSecPerSec;
                //select test two read fd,one is from user, one is from default 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)){
                            if(fd == serverfd){//server listen fd
                              //This is a new connection.
                              tcpaddr_len = sizeof(tcpaddr);
                              //the accept tcpaddr is diffrent from bind.it get cient ip
                              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);
                                   FD_SET(client, &fdset);
                                   if(client > max_fd)
                                        max_fd = client;
                                    //connect proxy server  
                                    clientfd=clientconn();
                                    if (clientfd==-1) {
                                        printf("clientfd fail\n");
                                        return -1;
                                    }
                                    printf("create a new connect to default proxy: %d\n", clientfd);
                                    FD_SET(clientfd, &fdset);
                                    if(clientfd > max_fd) 
                                         max_fd = clientfd;
                                 //map user and default proxy socket;eg:user fd is 1,proxy fd is 5
                                //proxy[5]=1,user[1]=5,这样将user connect的fd和proxy connect的fd绑定
                                    proxy[client]=clientfd;
                                    user[clientfd]=client;
                                }else{
                                          //debug scoket error
                                           perror("accept()");
                                     }
                             }else{
                                 memset(line,0x00,msglen);
                                 //此处可以优化为循环读
                                 retVal = read(fd, line, msglen);
                                  //retVal = recv(fd, line, msglen,0);
                                 if(retVal <= 0){
                                    if (errno==EINTR) //中断
                                       continue;
                                    else
                                       closemap(fd);
                                 }else{//forword data
                                    if (proxy[fd]!=0) {
                                        fdmap=proxy[fd];
                                        ret=write(fdmap,line,retVal);
                                        //ret=send(fdmap,line,retVal,MSG_NOSIGNAL);
                                        if (ret <=0) {
                                           if (errno==EINTR)
                                                continue;
                                           else {
                                                printf("write to proxy srever error:%d:%s\n",
    errno,strerror(errno));
                                                closemap(fdmap);
                                                }
                                         } else  {
                                             printf("write to default proxy\n");
                                          } 
                                           break;
                                     } else if (user[fd]!=0) {
                                          fdmap=user[fd];
                                          printf("from %d to %d\n",fd, fdmap);
                                          ret=write(fdmap,line,retVal);
                                          //ret=send(fdmap,line,retVal,MSG_NOSIGNAL);
                                          if (ret <0) {
                                              if (errno==EINTR) 
                                                 continue;
                                              else {
                                                 printf("write to user error:%d:%s\n",
    errno,strerror(errno));
                                                 closemap(fdmap);
                                            }
                                         } else {
                                                 printf("write to user\n");
                                          }
                                             break;
                                       }
                                     }
                                }
                            }
                    }
            } else if (count ==0) {
                    continue;
            }else {
                    printf("error:fd=%d\n",fd);
                    break;
            }
        }
            for (fd=0;fd<=max_fd;fd++) {
                    if(FD_ISSET(fd, &fdset)){
                            close (fd);
                    }
            }
            fclose(C_Logfile_fd);
    }
    int bindlisten() {
            struct sockaddr_in    tcpaddr;
            struct in_addr          intfIpAddr;
            int tcpaddr_len;
            int sockfd;
            int client;
            int port=7000;
            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;
            if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(char *)(&on),sizeof(on))<0)
            {
                    printf("so_resueadd failed,error %d:%s\n",errno,strerror(errno));
                    return -2;
            }
            // make bind call
            if ((retVal = bind(sockfd, (struct sockaddr *)(&tcpaddr), sizeof(tcpaddr)))< 0 ) 
            {
                fprintf(C_Logfile_fd,"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 default proxy 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);
            //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;
    }
    //close proxy and user socket fd together
    void closemap (int fd) {
            //The socket is wrong or closed.
            close(fd);
            FD_CLR(fd, &fdset);
            printf("close %d\n",fd);
            //remove the socketfd;one sockfd close ,peer sockfd close
             if (proxy[fd]!=0) {
                    temp=proxy[fd];
                    close (proxy[fd]);
                    printf("client close %d\n",proxy[fd]);
                    FD_CLR(proxy[fd], &fdset);
                    proxy[fd]=0;
                    user[temp]=0;
            } else if (user[fd]!=0) {
                    temp=user[fd];
                    close(user[fd]);
                    printf("server  close %d\n",user[fd]);
                    FD_CLR(user[fd], &fdset);
                    user[fd]=0;
                    proxy[temp]=0;
            }
    }
    

    相关文章

      网友评论

          本文标题:代理服务器select版本

          本文链接:https://www.haomeiwen.com/subject/qokeyktx.html