• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 298  文章 - 377  trackbacks - 0
            <2016年6月>
            2930311234
            567891011
            12131415161718
            19202122232425
            262728293012
            3456789

            常用鏈接

            留言簿(34)

            隨筆分類

            隨筆檔案

            文章檔案

            相冊

            收藏夾

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            /*************************************  
                *   一個基礎(chǔ)的代理服務(wù)器類  
                *************************************  
                */  
              import   java.net.*;  
              import   java.io.*;  
               
              public   class   HttpProxy   extends   Thread   {  
                      static   public   int   CONNECT_RETRIES=5;  
                      static   public   int   CONNECT_PAUSE=5;  
                      static   public   int   TIMEOUT=50;  
                      static   public   int   BUFSIZ=1024;  
                      static   public   boolean   logging   =   false;  
                      static   public   OutputStream   log=null;  
                      //   傳入數(shù)據(jù)用的Socket  
                      protected   Socket   socket;  
                      //   上級代理服務(wù)器,可選  
                      static   private   String   parent=null;  
                      static   private   int   parentPort=-1;  
                      static   public   void   setParentProxy(String   name,   int   pport)   {  
              parent=name;  
              parentPort=pport;  
                      }  
               
                      //   在給定Socket上創(chuàng)建一個代理線程。  
                      public   HttpProxy(Socket   s)   {   socket=s;   start();   }  
               
                      public   void   writeLog(int   c,   boolean   browser)   throws   IOException   {  
              log.write(c);  
                      }  
               
                      public   void   writeLog(byte[]   bytes,int   offset,   int   len,   boolean   browser)   throws   IOException   {  
              for   (int   i=0;i<len;i++)   writeLog((int)bytes[offset+i],browser);  
                      }  
               
               
                      //   默認(rèn)情況下,日志信息輸出到  
                      //   標(biāo)準(zhǔn)輸出設(shè)備  
                      //   派生類可以覆蓋它  
                      public   String   processHostName(String   url,   String   host,   int   port,   Socket   sock)   {  
              java.text.DateFormat   cal=java.text.DateFormat.getDateTimeInstance();  
              System.out.println(cal.format(new   java.util.Date())   +   "   -   "   +   url   +   "   "    
                                          +   sock.getInetAddress()+"\n");  
              return   host;  
                      }  
               
               
               
                      //   執(zhí)行操作的線程  
                      public   void   run()   {  
              String   line;  
              String   host;  
              int   port=80;  
                              Socket   outbound=null;  
              try   {  
                      socket.setSoTimeout(TIMEOUT);  
                      InputStream   is=socket.getInputStream();  
                      OutputStream   os=null;  
                      try   {  
                                              //   獲取請求行的內(nèi)容  
              line="";  
              host="";  
              int   state=0;  
              boolean   space;  
              while   (true)   {  
                      int   c=is.read();  
                      if   (c==-1)   break;  
                      if   (logging)   writeLog(c,true);  
                      space=Character.isWhitespace((char)c);    
                      switch   (state)   {  
                      case   0:  
              if   (space)   continue;    
                              state=1;  
                      case   1:  
              if   (space)   {  
                      state=2;  
                      continue;  
              }  
              line=line+(char)c;  
              break;  
                      case   2:  
              if   (space)   continue;   //   跳過多個空白字符  
                                  state=3;  
                      case   3:  
              if   (space)   {  
                      state=4;    
                                                                      //   只取出主機(jī)名稱部分  
                      String   host0=host;  
                      int   n;  
                      n=host.indexOf("http://");  
                      if   (n!=-1)   host=host.substring(n+2);  
                      n=host.indexOf('/');  
                      if   (n!=-1)   host=host.substring(0,n);  
                                                                      //   分析可能存在的端口號  
                      n=host.indexOf(":");  
                      if   (n!=-1)   {    
              port=Integer.parseInt(host.substring(n+1));  
              host=host.substring(0,n);  
                      }  
                      host=processHostName(host0,host,port,socket);  
                      if   (parent!=null)   {  
              host=parent;  
              port=parentPort;  
                      }  
                      int   retry=CONNECT_RETRIES;  
                      while   (retry--!=0)   {  
              try   {  
                      outbound=new   Socket(host,port);  
                      break;  
              }   catch   (Exception   e)   {   }  
                                                                              //   等待  
              Thread.sleep(CONNECT_PAUSE);  
                      }  
                      if   (outbound==null)   break;  
                      outbound.setSoTimeout(TIMEOUT);  
                      os=outbound.getOutputStream();  
                      os.write(line.getBytes());  
                      os.write('   ');  
                      os.write(host0.getBytes());  
                      os.write('   ');  
                      pipe(is,outbound.getInputStream(),os,socket.getOutputStream());  
                      break;  
              }  
              host=host+(char)c;  
              break;  
                      }  
              }  
                      }  
                      catch   (IOException   e)   {   }  
               
                      }   catch   (Exception   e)   {   }  
                      finally   {  
                      try   {   socket.close();}   catch   (Exception   e1)   {}  
                      try   {   outbound.close();}   catch   (Exception   e2)   {}  
                            }  
                      }  
               
               
                      void   pipe(InputStream   is0,   InputStream   is1,  
                                OutputStream   os0,     OutputStream   os1)   throws   IOException   {  
              try   {  
                      int   ir;  
                      byte   bytes[]=new   byte[BUFSIZ];  
                      while   (true)   {  
              try   {  
                      if   ((ir=is0.read(bytes))>0)   {  
              os0.write(bytes,0,ir);  
              if   (logging)   writeLog(bytes,0,ir,true);  
                      }  
                      else   if   (ir<0)  
              break;  
              }   catch   (InterruptedIOException   e)   {   }  
              try   {  
                      if   ((ir=is1.read(bytes))>0)   {  
              os1.write(bytes,0,ir);  
              if   (logging)   writeLog(bytes,0,ir,false);  
                      }  
                      else   if   (ir<0)    
              break;  
              }   catch   (InterruptedIOException   e)   {   }  
                      }  
              }   catch   (Exception   e0)   {  
                      System.out.println("Pipe異常:   "   +   e0);  
              }  
                      }  
               
               
                      static   public   void   startProxy(int   port,Class   clobj)   {  
              ServerSocket   ssock;  
              Socket   sock;  
                              try   {  
                      ssock=new   ServerSocket(port);  
                      while   (true)   {  
              Class   []   sarg   =   new   Class[1];  
              Object   []   arg=   new   Object[1];  
              sarg[0]=Socket.class;  
              try   {  
                      java.lang.reflect.Constructor   cons   =   clobj.getDeclaredConstructor(sarg);  
                      arg[0]=ssock.accept();  
                      cons.newInstance(arg);   //   創(chuàng)建HttpProxy或其派生類的實例  
              }   catch   (Exception   e)   {    
                      Socket   esock   =   (Socket)arg[0];  
                      try   {   esock.close();   }   catch   (Exception   ec)   {}  
              }  
                      }  
              }   catch   (IOException   e)   {  
              }  
                      }  
               
               
                      //   測試用的簡單main方法  
                      static   public   void   main(String   args[])   {  
              System.out.println("在端口808啟動代理服務(wù)器\n");  
              HttpProxy.log=System.out;  
              HttpProxy.logging=false;  
              HttpProxy.startProxy(808,HttpProxy.class);  
                          }  
                      }  
              //   HttpProxy的簡單派生類  
              //   不記錄主機(jī)名字  
              //   在日志輸出的每一行前面加上一個'*'  
               
              import   java.io.*;  
              import   java.net.*;  
               
              public   class   SubHttpProxy   extends   HttpProxy   {  
                      static   private   boolean   first=true;  
                      public   SubHttpProxy(Socket   s)   {  
              super(s);  
                      }  
                      public   void   writeLog(int   c,   boolean   browser)   throws   IOException   {  
              if   (first)   log.write('*');  
              first=false;  
              log.write(c);  
              if   (c=='\n')   log.write('*');  
                      }  
                      public   String   processHostName(String   url,   String   host,   int   port,   Socket   sock)   {  
              //   直接返回  
              return   host;  
                      }  
                      //   測試用的簡單main方法  
                      static   public   void   main(String   args[])   {  
              System.out.println("在端口808啟動代理服務(wù)器\n");  
              HttpProxy.log=System.out;  
              HttpProxy.logging=true;  
              HttpProxy.startProxy(808,SubHttpProxy.class);  
                          }  
               
               
              }  
            posted on 2008-10-21 02:02 聶文龍 閱讀(7124) 評論(11)  編輯 收藏 引用

            FeedBack:
            # re: 代理服務(wù)器代碼 2008-10-21 02:03 聶文龍
            不要心里老是想著只要拿到源代碼就可以直接去用,因為對rfc1928、rfc1929研究是必要的,因為在調(diào)試程序的時候,你一定要知道協(xié)議才可以調(diào),我現(xiàn)在給一些相關(guān)的文檔給你,也許比那些代碼對你更加有用處:

            用socks5進(jìn)行udp發(fā)送數(shù)據(jù)的過程:

            你的目的是要和服務(wù)器做UDP的數(shù)據(jù)傳送。
            步驟:
            1,和代理建立tcp聯(lián)接,(你已經(jīng)完成)
            2,向代理發(fā)送版本的請求信息,
            我的實現(xiàn):
            void CCommunicator::SendVer ()
            {
            int datasize = 6;
            char tempbuf[6];

            tempbuf[0] = 5;
            tempbuf[1] = 4;//標(biāo)示后面所根的字接數(shù)
            tempbuf[2] = 0;
            tempbuf[3] = 1;
            tempbuf[4] = 2;
            tempbuf[5] = 3;
            int senddatalen;
            senddatalen = send(m_sock, (char *)tempbuf, 6, 0 );
            }
            這一步,你已經(jīng)返回成功,是嗎?
            如果失敗,斷開建立的tcp聯(lián)接,
            如果成功,如果需要用戶驗證則進(jìn)行步驟3,否則進(jìn)行4,
            3,如果需要用戶驗證,則
            類似:
            BOOL CCommunicator::SendUserTest()
            {
            int usernamelen=0;
            int userpasslen=0;
            usernamelen = m_strTestUserName.GetLength();
            userpasslen = m_strTestUserPass.GetLength();
            char tempbuf[100];

            tempbuf[0] = 5;
            tempbuf[1] = usernamelen;//標(biāo)示后面所根的字接數(shù)
            strcpy(&tempbuf[2],m_strTestUserName);

            tempbuf[2+usernamelen] = userpasslen;
            strcpy((char *)&tempbuf [3+usernamelen] ,m_strTestUserPass);

            int senddatalen;
            int len;
            len = usernamelen +userpasslen + 3;
            senddatalen = send(m_sock, (char *)tempbuf, len, 0 );
            }
            如果失敗,斷開建立的tcp聯(lián)接,
            如果用戶返回成功,步驟4
            4,發(fā)送請求的協(xié)議
            類似:
            void CCommunicator::SendRequestUDP ()
            {

            int const datasize = 10;
            BYTE tempbuf[datasize];
            tempbuf[0] = 5;
            tempbuf[1] = 3;//標(biāo)示UDP連接
            tempbuf[2] = 0;
            tempbuf[3] = 1;
            tempbuf[4] = 0;
            tempbuf[5] = 0;
            tempbuf[6] = 0;
            tempbuf[7] = 0;
            *((SHORT*)(&(tempbuf[8]))) = m_uBindUDPPort;
            //UDP在客戶端綁定的端口,就是你本地機(jī)器的做udp數(shù)據(jù)傳送的端口,調(diào)用
            // socket函數(shù)后,再調(diào)用bind()來邦定一個端口。
            char temp;
            temp = tempbuf[8] ;
            tempbuf[8] = tempbuf[9];
            tempbuf[9] = temp;

            int senddatalen = send(m_sock, (char *)tempbuf, datasize, 0 );
            }
            如果失敗,斷開建立的tcp聯(lián)接,
            如果返回成功,驗證完畢!步驟5
            5,真正的數(shù)據(jù)傳送,用代理傳送的時候,數(shù)據(jù)包的前面加上10個字節(jié)
            類似:
            void CCommunicator::CopyDataHead(BYTE * ptempbuf)
            {
            struct in_addr addr;
            addr.s_addr = inet_addr(“202.220.33.333”);//這個ip是服務(wù)器端的ip

            ptempbuf[0] = 0;
            ptempbuf[1] = 0;
            ptempbuf[2] = 0;
            ptempbuf[3] = 1;
            ptempbuf[4] = (char)addr.S_un.S_un_b.s_b1;;
            ptempbuf[5] = (char)addr.S_un.S_un_b.s_b2;
            ptempbuf[6] = (char)addr.S_un.S_un_b.s_b3;
            ptempbuf[7] = (char)addr.S_un.S_un_b.s_b4;

            *((SHORT*)(&(ptempbuf[8]))) = m_uServerUDPPort;//服務(wù)器的端口,就是你最終要發(fā)到那個服務(wù)器的端口,也就是你的qq服務(wù)器。
            char temp;
            temp = ptempbuf[8] ;
            ptempbuf[8] = ptempbuf[9];
            ptempbuf[9] = temp;
            }
            真正發(fā)送的時候類似:
            int CCommunicator::SendBufferUDP(LPBYTE lpBuf,int nLen)
            {
            BYTE tempbuf[1000];
            int iHeadData = 0;
            struct sockaddr_in her;
            her.sin_family = AF_INET;
            her.sin_addr.s_addr = inet_addr(m_szProxyAddr);//代理服務(wù)器
            her.sin_port = htons(m_uSocksPort);//發(fā)送請求的時候返回的代理服務(wù)器端的端口,記住,這是最重要的。
            CopyDataHead(tempbuf);
            iHeadData = 10;
            nLen=nLen + 10;
            int addr_len;
            addr_len = sizeof(struct sockaddr);

            CopyMemory((char *)&tempbuf[iHeadData],lpBuf,nLen);
            int returndatalen = sendto(m_socket,(char *)tempbuf,nLen,0,(struct sockaddr *)&her,addr_len);

            }
            希望對你有幫助!  回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2008-10-21 02:04 聶文龍
            傳透代理服務(wù)器的編程

            關(guān)鍵字 代理服務(wù)器、Socks4、Socks5、Http代理
            原作者姓名 allfresh
            文章原始出處 http://www.allfresh.net/program/proxy.htm
            正文
            在網(wǎng)絡(luò)程序設(shè)計過程中,我們經(jīng)常要與各種類型的代理服務(wù)器打交道,比如在企業(yè)內(nèi)部網(wǎng)通過代理去訪問Internet網(wǎng)上的服務(wù)器等等,一般代理服務(wù)器支持幾種常見的代理協(xié)議標(biāo)準(zhǔn),如Socks4,Socks5,Http代理,其中Socks5需要用戶驗證,代理相對復(fù)雜。我在查閱RFC文檔和相關(guān)資料后,特總結(jié)一些TCP協(xié)議穿透代理服務(wù)器的程序片斷,希望對大家有所幫助。

            //使用到的結(jié)構(gòu)
            struct sock4req1
            {
             char VN;
             char CD;
             unsigned short Port;
             unsigned long IPAddr;
             char other[1];
            };

            struct sock4ans1
            {
             char VN;
             char CD;
            };

            struct sock5req1
            {
             char Ver;
             char nMethods;
             char Methods[255];
            };

            struct sock5ans1
            {
             char Ver;
             char Method;
            };

            struct sock5req2
            {
             char Ver;
             char Cmd;
             char Rsv;
             char Atyp;
             char other[1];
            };

            struct sock5ans2
            {
             char Ver;
             char Rep;
             char Rsv;
             char Atyp;
             char other[1];
            };

            struct authreq
            {
             char Ver;
             char Ulen;
             char Name[255];
             char PLen;
             char Pass[255];
            };

            struct authans
            {
             char Ver;
             char Status;
            };

            //通過Socks4方式代理
            if( !ClientSock.Connect( g_ProxyInfo.m_strProxyIP,g_ProxyInfo.m_nProxyPort) )
            {
              m_sError = _T("不能連接到代理服務(wù)器!");
              ClientSock.Close();
              return FALSE;
            }
            char buff[100];
            memset(buff,0,100);
            struct sock4req1 *m_proxyreq;
            m_proxyreq = (struct sock4req1 *)buff;
            m_proxyreq->VN = 4;
            m_proxyreq->CD = 1;
            m_proxyreq->Port = ntohs(GetPort());
            m_proxyreq->IPAddr = inet_addr(GetServerHostName());
            ClientSock.Send(buff,9);
            struct sock4ans1 *m_proxyans;
            m_proxyans = (struct sock4ans1 *)buff;
            memset(buff,0,100);
            ClientSock.Receive(buff,100);
            if(m_proxyans->VN != 0 || m_proxyans->CD != 90)
            {
             m_sError = _T("通過代理連接主站不成功!");
             ClientSock.Close();
             return FALSE;
            }




            //通過Socks5方式代理
            if( !ClientSock.Connect( g_ProxyInfo.m_strProxyIP,g_ProxyInfo.m_nProxyPort) )
            {
             m_sError = _T("不能連接到代理服務(wù)器!");
             ClientSock.Close();
             return FALSE;
            }
            char buff[600];
            struct sock5req1 *m_proxyreq1;
            m_proxyreq1 = (struct sock5req1 *)buff;
            m_proxyreq1->Ver = 5;
            m_proxyreq1->nMethods = 2;
            m_proxyreq1->Methods[0] = 0;
            m_proxyreq1->Methods[1] = 2;
            ClientSock.Send(buff,4);
            struct sock5ans1 *m_proxyans1;
            m_proxyans1 = (struct sock5ans1 *)buff;
            memset(buff,0,600);
            ClientSock.Receive(buff,600);
            if(m_proxyans1->Ver != 5 || (m_proxyans1->Method!=0 && m_proxyans1->Method!=2))
            {
             m_sError = _T("通過代理連接主站不成功!");
             ClientSock.Close();
             return FALSE;
            }
            if(m_proxyans1->Method == 2)
            {
             int nUserLen = strlen(g_ProxyInfo.m_strProxyUser);
             int nPassLen = strlen(g_ProxyInfo.m_strProxyPass);
             struct authreq *m_authreq;
             m_authreq = (struct authreq *)buff;
             m_authreq->Ver = 1;
             m_authreq->Ulen = nUserLen;
             strcpy(m_authreq->Name,g_ProxyInfo.m_strProxyUser);
             m_authreq->PLen = nPassLen;
             strcpy(m_authreq->Pass,g_ProxyInfo.m_strProxyPass);
             ClientSock.Send(buff,513);
             struct authans *m_authans;
             m_authans = (struct authans *)buff;
             memset(buff,0,600);
             ClientSock.Receive(buff,600);
             if(m_authans->Ver != 1 || m_authans->Status != 0)
             {
              m_sError = _T("代理服務(wù)器用戶驗證不成功!");
              ClientSock.Close();
             return FALSE;
             }
            }
            struct sock5req2 *m_proxyreq2;
            m_proxyreq2 = (struct sock5req2 *)buff;
            m_proxyreq2->Ver = 5;
            m_proxyreq2->Cmd = 1;
            m_proxyreq2->Rsv = 0;
            m_proxyreq2->Atyp = 1;
            unsigned long tmpLong = inet_addr(GetServerHostName());
            unsigned short port = ntohs(GetPort());
            memcpy(m_proxyreq2->other,&tmpLong,4);
            memcpy(m_proxyreq2->other+4,&port,2);
            ClientSock.Send(buff,sizeof(struct sock5req2)+5);
            struct sock5ans2 *m_proxyans2;
            memset(buff,0,600);
            m_proxyans2 = (struct sock5ans2 *)buff;
            ClientSock.Receive(buff,600);
            if(m_proxyans2->Ver != 5 || m_proxyans2->Rep != 0)
            {
             m_sError = _T("通過代理連接主站不成功!");
             ClientSock.Close();
             return FALSE;
            }




            //通過HTTP方式代理
            if( !ClientSock.Connect( g_ProxyInfo.m_strProxyIP,g_ProxyInfo.m_nProxyPort) )
            {
             m_sError = _T("不能連接到代理服務(wù)器!");
             ClientSock.Close();
             return FALSE;
            }
            char buff[600];
            sprintf( buff, "%s%s:%d%s","CONNECT ",GetServerHostName(),GetPort()," HTTP/1.1\r\nUser-Agent: MyApp/0.1\r\n\r\n");
            ClientSock.Send(buff,strlen(buff)); //發(fā)送請求
            memset(buff,0,600);
            ClientSock.Receive(buff,600);
            if(strstr(buff, "HTTP/1.0 200 Connection established") == NULL) //連接不成功
            {
             m_sError = _T("通過代理連接主站不成功!");
             ClientSock.Close();
             return FALSE;
            }


            我們一般先與代理服務(wù)器連通,然后向代理服務(wù)器發(fā)送代理驗證的用戶名和密碼(如果需要,如Socks5代理),驗證成功后,再向代理服務(wù)器發(fā)送需要連接的目的地址和端口。以上代碼僅用于TCP連接,如果在內(nèi)部網(wǎng)偵聽或通過UDP協(xié)議發(fā)送信息,可查閱RFC1829等文檔資料。

            <正文完>   回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2008-10-21 02:08 聶文龍
            使用socks4 socks5 http代理的客戶端

            ///定義的結(jié)構(gòu)
            struct sock4req1
            {
            char VN;
            char CD;
            unsigned short Port;
            unsigned long IPAddr;
            char other[1];
            };

            struct sock4ans1
            {
            char VN;
            char CD;
            };

            struct sock5req1
            {
            char Ver;
            char nMethods;
            char Methods[255];
            };

            struct sock5ans1
            {
            char Ver;
            char Method;
            };

            struct sock5req2
            {
            char Ver;
            char Cmd;
            char Rsv;
            char Atyp;
            unsigned long IPAddr;
            unsigned short Port;

            // char other[1];
            };

            struct sock5ans2
            {
            char Ver;
            char Rep;
            char Rsv;
            char Atyp;
            char other[1];
            };

            struct authreq
            {
            char Ver;
            char Ulen;
            char Name[255];
            char PLen;
            char Pass[255];
            };

            struct authans
            {
            char Ver;
            char Status;
            };


            ///////////
            ///////////代碼片段
            void CTestDlg::OnSocks4()
            {
            CString m_sError;
            ClientSock.Create();

            //Socks4代理服務(wù)器端口及地址
            //if( !ClientSock.Connect( "195.65.215.38",1080) )
            if( !ClientSock.Connect( "192.168.123.194",1080) )
            {
            m_sError = _T("不能連接到代理服務(wù)器!");
            ClientSock.Close();
            MessageBox(m_sError);
            return ;
            }

            char buff[100];
            memset(buff,0,100);
            struct sock4req1 *m_proxyreq;
            m_proxyreq = (struct sock4req1 *)buff;
            m_proxyreq->VN = 4;
            m_proxyreq->CD = 1;
            m_proxyreq->Port = ntohs(21);
            m_proxyreq->IPAddr = inet_addr("219.201.39.50");
            strcpy(m_proxyreq->other , "");
            ClientSock.Send(buff,9);
            struct sock4ans1 *m_proxyans;
            m_proxyans = (struct sock4ans1 *)buff;
            memset(buff,0,100);
            ClientSock.Receive(buff,100);
            if(m_proxyans->VN != 0 || m_proxyans->CD != 90)
            {
            m_sError = _T("通過代理連接主站不成功!");
            ClientSock.Close();
            MessageBox(m_sError);
            return ;
            }



            //連接已經(jīng)建立,發(fā)送及接收數(shù)據(jù)
            memset(buff,0,100);
            strcpy(buff,"Hello!");
            ClientSock.Send(buff,sizeof(buff));
            memset(buff,0,100);
            ClientSock.Receive(buff,100);
            MessageBox(buff);
            ClientSock.Close();

            }

            void CTestDlg::OnSocks5()
            {
            // TODO: Add your control notification handler code here
            //http://my.nbip.net/homepage/nblulei/ttdl/sockdllb.htm

            CString m_sError;
            ClientSock.Create();
            //Socks5代理服務(wù)器端口及地址
            //if( !ClientSock.Connect("61.238.12.84",12654) )
            if( !ClientSock.Connect("192.168.123.194",1080) )
            {
            m_sError = _T("不能連接到代理服務(wù)器!");
            ClientSock.Close();
            MessageBox(m_sError);
            return ;
            }
            char buff[600];
            struct sock5req1 *m_proxyreq1;
            m_proxyreq1 = (struct sock5req1 *)buff;
            m_proxyreq1->Ver = 5;
            m_proxyreq1->nMethods = 2;
            m_proxyreq1->Methods[0] = 0;
            m_proxyreq1->Methods[1] = 2;
            ClientSock.Send(buff,4);
            struct sock5ans1 *m_proxyans1;
            m_proxyans1 = (struct sock5ans1 *)buff;
            memset(buff,0,600);
            ClientSock.Receive(buff,600);
            if(m_proxyans1->Ver != 5 || (m_proxyans1->Method!=0 && m_proxyans1->Method!=2))
            {
            m_sError = _T("通過代理連接主站不成功!");
            ClientSock.Close();
            MessageBox(m_sError);
            return ;
            }
            if(m_proxyans1->Method == 2)
            {
            int nUserLen = strlen("alon");
            int nPassLen = strlen("alon");
            struct authreq *m_authreq = {0};
            m_authreq = (struct authreq *)buff;
            m_authreq->Ver = 1;
            m_authreq->Ulen = nUserLen;
            strcpy(m_authreq->Name,"alon");
            m_authreq->PLen = nPassLen;
            strcpy(m_authreq->Pass,"alon");
            ClientSock.Send(buff,513);
            struct authans *m_authans;
            m_authans = (struct authans *)buff;
            memset(buff,0,600);
            ClientSock.Receive(buff,600);
            if(m_authans->Ver != 1 || m_authans->Status != 0)
            {
            m_sError = _T("代理服務(wù)器用戶驗證不成功!");
            ClientSock.Close();
            MessageBox(m_sError);
            return ;
            }
            }
            struct sock5req2 *m_proxyreq2;
            m_proxyreq2 = (struct sock5req2 *)buff;
            m_proxyreq2->Ver = 5;
            m_proxyreq2->Cmd = 1;
            m_proxyreq2->Rsv = 0;
            m_proxyreq2->Atyp = 1;
            m_proxyreq2->IPAddr = inet_addr("219.201.39.50");
            m_proxyreq2->Port = ntohs(21);


            ClientSock.Send(buff,sizeof(struct sock5req2));
            struct sock5ans2 *m_proxyans2;
            memset(buff,0,600);
            m_proxyans2 = (struct sock5ans2 *)buff;
            ClientSock.Receive(buff,600);
            if(m_proxyans2->Ver != 5 || m_proxyans2->Rep != 0)
            {
            m_sError = _T("通過代理連接主站不成功!");
            ClientSock.Close();
            MessageBox(m_sError);
            return ;
            }



            //連接已經(jīng)建立,發(fā)送及接收數(shù)據(jù)
            memset(buff,0,600);
            strcpy(buff,"Hello!");
            ClientSock.Send(buff,sizeof(buff));
            memset(buff,0,600);
            ClientSock.Receive(buff,600);
            MessageBox(buff);
            ClientSock.Close();
            }


            void CTestDlg::OnHttp()
            {
            // TODO: Add your control notification handler code here
            CString m_sError;
            ClientSock.Create();
            //if( !ClientSock.Connect("61.145.123.202",3128) )
            if( !ClientSock.Connect("211.92.143.19",3128) )
            //if( !ClientSock.Connect("WWW.TOM.COM",80) )
            {
            m_sError = _T("不能連接到代理服務(wù)器!");
            ClientSock.Close();
            MessageBox(m_sError);
            return ;
            }

            char buff[600] = {0};
            // sprintf( buff, "%s%s:%d%s","CONNECT ","219.201.39.50",21," HTTP/1.1\r\nUser-Agent: MyApp/0.1\r\n\r\n");
            sprintf( buff, "%s%s:%d%s","CONNECT ","219.201.39.50",21," HTTP/1.1\r\nUser-Agent: CERN-LineMode/2.15 libwww/2.17b3\r\n\r\n");
            // sprintf( buff, "%s%s:%d%s","CONNECT ","www.tom.com",80," HTTP/1.1\r\nUser-Agent: CERN-LineMode/2.15 libwww/2.17b3\r\n\r\n");
            // sprintf( buff, "%s%s","GET ","HTTP://WWW.TOM.COM HTTP/1.1\r\n\r\n");

            ClientSock.Send(buff,strlen(buff)); //發(fā)送請求
            memset(buff,0,600);
            ClientSock.Receive(buff,600);
            if(strstr(buff, "HTTP/1.0 200 Connection established") == NULL) //連接不成功
            {
            m_sError = _T("通過代理連接主站不成功!");
            ClientSock.Close();
            return ;
            }


            /* if( strstr(buff, "Error 403") )
            {
            //return GoError(PROXYERROR_PROXYDISABLE); //代理服務(wù)器拒絕請求
            }

            if( strstr(buff, "407 Proxy authentication required") ) //需要身份驗證
            {
            //return GoError(PROXYERROR_USERNAMEORPASSWORD); //用戶身份校檢不成功
            }
            if( strstr(buff, "Connection refuesed") )
            {
            //return GoError(PROXYERROR_CONNECTHOSTSERVER); //通過代理連接主站不成功
            }
            if( strstr(buff, "Access Denied") )
            {
            //return GoError(PROXYERROR_USERNAMEORPASSWORD); //用戶身份校檢不成功
            }
            if(strstr(buff, "Connection refused by Remote Host") )
            {
            //return GoError(PROXYERROR_CONNECTHOSTSERVER); //通過代理連接主站不成功
            }

            ClientSock.Close();
            */




            //連接已經(jīng)建立,發(fā)送及接收數(shù)據(jù)
            memset(buff,0,600);
            strcpy(buff,"Hello!");
            ClientSock.Send(buff,sizeof(buff));
            memset(buff,0,600);
            ClientSock.Receive(buff,600);
            MessageBox(buff);
            ClientSock.Close();


            }


            /////////
            ///另附一些http的請求和返回
            發(fā)送一:
            CONNECT 61.135.158.91:80 HTTP/1.1
            User-Agent: MyApp/0.1


            發(fā)送二:
            CONNECT 61.135.158.91:80 HTTP/1.1
            User-Agent: CERN-LineMode/2.15 libwww/2.17b3


            發(fā)送三:
            CONNECT 127.0.0.1:2222 HTTP/1.0
            User-agent: MyApp/1.0
            Proxy-authorization: enter xxxxxx


            接收一:
            HTTP/1.0 403 Forbidden
            Server: Topproxy-2.0/
            Mime-Version: 1.0
            Date: Thu, 18 Nov 2004 16:37:53 GMT
            Content-Type: text/html
            Content-Length: 718
            Expires: Thu, 18 Nov 2004 16:37:53 GMT
            X-Squid-Error: ERR_ACCESS_DENIED 0
            X-Cache: MISS fro


            接收二:
            HTTP/1.0 502 Proxy Error ( SSL port specified is not allowed. )
            Via: 1.0 PROXY
            Pragma: no-cache
            Cache-Control: no-cache
            Content-Type: text/html

            <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
            <html>

            <head>
            <meta http-equiv="Conten"


            接收三:
            HTTP/1.1 403 Forbidden
            Date: Sat, 20 Nov 2004 14:33:13 GMT
            Content-Length: 257
            Content-Type: text/html
            Server: NetCache appliance (NetApp/5.6R1D6)

            <HTML>
            <HEAD><TITLE>403 Forbidden</TITLE></HEAD>
            <BODY>
            <H1>Forbidden</H1>
            <H4>
            You were"



              回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2008-10-21 02:12 聶文龍
            簡單代理服務(wù)器C代碼實現(xiàn)(SOLARIS)

            /*
            ** 編寫:無可非議
            ** 來源:WWW.20CN.NET
            ** 注意:請注明轉(zhuǎn)貼來源
            */

            #include <stdio.h>
            #include <sys/types.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <signal.h>
            #include <arpa/inet.h>
            #include <netdb.h>
            #include <sys/wait.h>
            #include <unistd.h>
            #include <string.h>
            #include <stdlib.h>
            #include <pthread.h>
            #include <sys/stat.h>

            int m_MainId = 0; //主進(jìn)程ID
            int m_ListenSocket = 0; //偵聽套接字
            char m_ConnectAddr[256] = {0}; //目標(biāo)地址
            char m_ConnectPort[256] = {0}; //目標(biāo)端口

            /*
            ** 函數(shù)名稱: GetListenSocket
            ** 函數(shù)功能: 生成偵聽套接字
            ** 傳入?yún)?shù): Port : 偵聽端口
            ** 傳出參數(shù): 無
            ** 引用函數(shù): 無
            ** 返回值 : 偵聽套接字,為0時表示生成套接字失敗,其他為套接字句柄
            ** 備注 : 無
            */
            int GetListenSocket(int Port)
            {
            struct sockaddr_in m_LisAddr = {0};
            int m_Socket = 0;
            int m_AddrLen = sizeof(struct sockaddr_in);

            //配置端口信息
            m_LisAddr.sin_family = AF_INET;
            m_LisAddr.sin_port = htons(Port);
            m_LisAddr.sin_addr.s_addr = INADDR_ANY;

            //創(chuàng)建套接字
            if ((m_Socket = socket(AF_INET,SOCK_STREAM,0)) < 0 )
            {
            //創(chuàng)建套接字失敗
            return 0;
            }

            //綁定套接字
            if(bind(m_Socket, (sockaddr*)&m_LisAddr , m_AddrLen) < 0 )
            {
            //綁定套接字失敗
            close(m_Socket);
            return 0;
            }

            //偵聽套接字
            if(listen(m_Socket,5))
            {
            //偵聽套接字失敗
            close(m_Socket);
            return 0;
            }

            //偵聽套接字生成成功
            return m_Socket;
            }

            /*
            ** 函數(shù)名稱: GetConnectSocket
            ** 函數(shù)功能: 生成連接套接字
            ** 傳入?yún)?shù): pServerAddr : 連接地址 pServerPort : 連接端口
            ** 傳出參數(shù): 無
            ** 引用函數(shù): 無
            ** 返回值 : 連接套接字,為0時表示生成套接字失敗,其他為套接字句柄
            ** 備注 : 無
            */
            int GetConnectSocket(char* pServerAddr,char* pServerPort)
            {
            struct sockaddr_in m_ServerAddr = {0};
            int m_AddrLen = sizeof(struct sockaddr_in);
            int m_Socket = 0;

            //初始化連接信息
            m_ServerAddr.sin_addr.S_un.S_addr = inet_addr(pServerAddr);
            m_ServerAddr.sin_port = htons(atoi(pServerPort));
            m_ServerAddr.sin_family = AF_INET;

            //創(chuàng)建發(fā)送套接字
            m_Socket = socket(AF_INET,SOCK_STREAM,0);
            if(m_Socket <= 0)
            {
            //失敗
            return NULL;
            }

            //連接客戶計算機(jī)
            if(connect(m_Socket,(sockaddr*)&m_ServerAddr,m_AddrLen) < 0 )
            {
            close(m_Socket);
            return NULL;
            }

            //連接成功
            return m_Socket;
            }

            /*
            ** 函數(shù)名稱: TransSocket
            ** 函數(shù)功能: 完成套接字?jǐn)?shù)據(jù)轉(zhuǎn)發(fā)
            ** 傳入?yún)?shù): m_SendSocket : 發(fā)送套接字 m_RecvSocket : 接收套接字
            ** 傳出參數(shù): 無
            ** 引用函數(shù): 無
            ** 返回值 : 無
            ** 備注 : 逆反完成全雙工
            */
            void TransSocket(int m_SendSocket,int m_RecvSocket)
            {
            char m_Buf[512 * 1024] = {0};
            int ret = 0;
            fd_set readset;
            struct timeval tm = {0};
            tm.tv_sec = 3600 * 24;

            FD_ZERO(&readset);
            FD_SET(m_RecvSocket,&readset);

            while(1)
            {
            if((select(m_RecvSocket + 1,&readset,NULL,NULL,&tm)
            <= 0))
            {
            //出錯
            break;
            }
            if(!FD_ISSET(m_RecvSocket,&readset)) continue;

            ret = recv(m_RecvSocket,m_Buf,512 * 1024 - 1,0);
            if(ret < 0)
            {
            //出錯
            break;
            }
            send(m_SendSocket,m_Buf,ret,0);
            }
            close(m_SendSocket);
            close(m_RecvSocket);
            }

            /*
            ** 函數(shù)名稱: SocketTrans
            ** 函數(shù)功能: 工作主函數(shù),完成數(shù)據(jù)轉(zhuǎn)發(fā),新進(jìn)程啟動
            ** 傳入?yún)?shù): m_SendSocket : 發(fā)送套接字 m_RecvSocket : 接收套接字
            ** 傳出參數(shù): 無
            ** 引用函數(shù): 無
            ** 返回值 : 無
            ** 備注 : 逆反完成全雙工
            */
            void SocketTrans()
            {
            struct sockaddr_in m_WorkAddr = {0};
            int m_191Socket = 0;
            int m_147socket = 0;
            int m_WorkAddrLen = 0;

            //開始任務(wù)執(zhí)行
            while(1)
            {
            //接受147的連接
            m_WorkAddrLen = sizeof(struct sockaddr_in);
            m_147socket = accept(m_ListenSocket,
            (sockaddr*)&m_WorkAddr , &m_WorkAddrLen);

            //檢查套接字合法性
            if(m_147socket < 0) continue;

            //連接191
            m_191Socket = GetConnectSocket(m_ConnectAddr,m_ConnectPort);
            if(m_191Socket == NULL)
            {
            close(m_147socket);
            continue;
            }

            int ret = fork();
            if(ret < 0)
            {
            //建立新進(jìn)程失敗
            printf("致命錯誤,無法建立新進(jìn)程!\n");
            fflush(stdout);
            close(m_191Socket);
            close(m_147socket);
            break;
            }
            else if(ret == 0)
            {
            //關(guān)閉原來端口
            close(m_ListenSocket);

            //建立二次子進(jìn)程,防止僵尸進(jìn)程
            ret = fork();
            if(ret < 0)
            {
            close(m_191Socket);
            close(m_147socket);
            _exit(0);
            }
            else if(ret == 0)
            {
            //接收進(jìn)程
            TransSocket(m_191Socket,m_147socket);
            _exit(0);
            }
            ret = fork();
            if(ret < 0)
            {
            close(m_191Socket);
            close(m_147socket);
            _exit(0);
            }
            else if(ret == 0)
            {
            //發(fā)送進(jìn)程
            TransSocket(m_147socket,m_191Socket);
            _exit(0);
            }
            close(m_191Socket);
            close(m_147socket);
            _exit(0);
            }

            //等待子線程結(jié)束
            close(m_191Socket);
            close(m_147socket);
            waitpid(ret,NULL,0);
            }
            }

            /*
            ** 函數(shù)名稱: sig_usr
            ** 函數(shù)功能: 進(jìn)程信號處理函數(shù)
            ** 傳入?yún)?shù): 無
            ** 傳出參數(shù): 無
            ** 引用函數(shù): 無
            ** 返回值 : 無
            ** 備注 : 處理進(jìn)程終止事件
            */
            static void sig_usr(int signo)
            {
            close(m_ListenSocket);
            if(m_MainId == getpid())
            kill(0,SIGKILL);
            exit(0);
            }

            static void sig_ign(int signo)
            {
            fprintf(stderr,"signal %d catched ,ignoring\n",signo);
            }

            int daemon_init()
            {
            pid_t pid;
            if((pid=fork())<0){
            return -1;
            }else if(pid!=0){
            exit(0);
            }
            setsid();
            umask(0);
            return 0;
            }

            /*
            ** 函數(shù)名稱: main
            ** 函數(shù)功能: 進(jìn)程主函數(shù)
            ** 傳入?yún)?shù): 無
            ** 傳出參數(shù): 無
            ** 引用函數(shù): MakeFilePath,GetMyInitInfo,SocketTrans
            ** 返回值 : 無
            ** 備注 : 為客戶接收進(jìn)程主函數(shù)
            */
            int main(int argc,char* argv[])
            {
            //檢查參數(shù)合法性
            if(argc != 4)
            {
            printf("格式:本地端口 目的地址 目的端口\n");
            fflush(stdout);
            return 0;
            }

            daemon_init();

            //登記信號事件
            signal(SIGTERM,sig_usr);
            signal(SIGINT,sig_usr);
            signal(SIGQUIT,sig_usr);
            signal(SIGPIPE,sig_ign);
            signal(SIGALRM,sig_ign);
            signal(SIGQUIT,sig_ign);
            signal(SIGFPE,sig_ign);
            signal(SIGILL,sig_ign);
            signal(SIGPIPE,sig_ign);
            signal(SIGSEGV,sig_ign);
            signal(SIGTRAP,sig_ign);
            signal(SIGTSTP,sig_ign);

            //取參數(shù)
            strcpy(m_ConnectAddr,argv[2]);
            strcpy(m_ConnectPort,argv[3]);

            //獲取偵聽套接字
            m_ListenSocket = GetListenSocket(atoi(argv[1]));
            if(m_ListenSocket == 0)
            {
            printf("偵聽端口[%s]失敗!\n",argv[1]);
            fflush(stdout);
            return 0;
            }

            m_MainId = getpid();
            //啟動文件接收偵聽線程
            SocketTrans();
            close(m_ListenSocket);
            return 0;
            }
              回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2008-10-21 02:19 聶文龍
            #include "stdafx.h"
            #include "Proxy.h"
            #include < winsock2.h > //WINSOCKET API 2。0
            #include < stdlib.h >
            #include < stdio.h >
            #include < string.h >


            #ifdef _DEBUG
            #define new DEBUG_NEW
            #undef THIS_FILE
            static char THIS_FILE[] = __FILE__;
            #endif


            /////////////////////////////////////////////////////////////////////////////


            #define HTTP "http://"
            #define FTP "ftp://"
            #define PROXYPORT 5001 //Proxy 端口
            #define BUFSIZE 10240 //緩沖區(qū)大小


            CWinApp theApp;


            using namespace std;


            UINT ProxyToServer(LPVOID pParam);
            UINT UserToProxyThread(void *pParam);


            strUCt SocketPair{
            SOCKET user_proxy; //socket : 本地機(jī)器到PROXY 服務(wù)機(jī)
            SOCKET proxy_server; //socket : PROXY 服務(wù)機(jī)到遠(yuǎn)程主機(jī)
            BOOL IsUser_ProxyClosed; // 本地機(jī)器到PROXY 服務(wù)機(jī)狀態(tài)
            BOOL IsProxy_ServerClosed; // PROXY 服務(wù)機(jī)到遠(yuǎn)程主機(jī)狀態(tài)
            };


            struct ProxyParam{
            char Address[256]; // 遠(yuǎn)程主機(jī)地址
            HANDLE User_SvrOK; // PROXY 服務(wù)機(jī)到遠(yuǎn)程主機(jī)的聯(lián)結(jié)狀態(tài)
            SocketPair *pPair; // 維護(hù)一組SOCKET的指針
            int Port; // 用來聯(lián)結(jié)遠(yuǎn)程主機(jī)的端口
            }; //這個結(jié)構(gòu)用來PROXY SERVER與遠(yuǎn)程主機(jī)的信息交換.


            SOCKET gListen_Socket; //用來偵聽的SOCKET。


            int StartServer() //啟動服務(wù)
            {
            WSADATA wsaData;
            sockaddr_in local;
            SOCKET listen_socket;


            if(::WSAStartup(0x202,&wsaData)!=0)
            {printf("\nError in Startup session.\n");WSACleanup();return -1;};



            local.sin_family=AF_INET;

            local.sin_addr.s_addr=INADDR_ANY;
            local.sin_port=htons(PROXYPORT);


            listen_socket=socket(AF_INET,SOCK_STREAM,0);
            if(listen_socket==INVALID_SOCKET)
            {printf("\nError in New a Socket.");WSACleanup();return -2;}


            if(::bind(listen_socket,(sockaddr *)&local,sizeof(local))!=0)
            {printf("\n Error in Binding socket."); WSACleanup();return -3; };


            if(::listen(listen_socket,5)!=0)
            {printf("\n Error in Listen."); WSACleanup(); return -4;}
            gListen_Socket=listen_socket;
            AfxBeginThread(UserToProxyThread,NULL); //啟動偵聽
            return 1;
            }


            int CloseServer() //關(guān)閉服務(wù)
            {
            closesocket(gListen_Socket);
            WSACleanup();
            return 1;
            }
            //分析接收到的字符,得到遠(yuǎn)程主機(jī)地址


            int GetAddressAndPort( char * str, char *address, int * port)
            {
            char buf[BUFSIZE], command[512], proto[128], *p;
            int j;
            sscanf(str,"%s%s%s",command,buf,proto);
            p=strstr(buf,HTTP);
            //HTTP
            if(p)
            {
            p+=strlen(HTTP);
            for(int i=0;i< strlen(p);i++)
            if( *(p+i)=='/') break;
            *(p+i)=0;
            strcpy(address,p);
            p=strstr(str,HTTP);
            for(int j=0;j< i+strlen(HTTP);j++)
            *(p+j)=' '; //去掉遠(yuǎn)程主機(jī)名: GET http://www.njust.edu.cn/ HTTP1.1 == > GET / HTTP1.1
            *port=80; //缺省的 http 端口
            }
            else
            {//FTP, 不支持, 下面的代碼可以省略.
            p=strstr(buf,FTP);
            if(!p) return 0;
            p+=strlen(FTP);
            for(int i=0;i< strlen(p);i++)
            if( *(p+i)=='/') break; //Get The Remote Host
            *(p+i)=0;
            for(j=0;j< strlen(p);j++)
            if(*(p+j)==':')
            {*port=atoi(p+j+1); //Get The Port
            *(p+j)=0;
            }
            else *port=21;



            strcpy(address,p);
            p=strstr(str,FTP);
            for(j=0;j< i+strlen(FTP);j++)

            *(p+j)=' ';
            }
            return 1;
            }


            // 取到本地的數(shù)據(jù),發(fā)往遠(yuǎn)程主機(jī)
            UINT UserToProxyThread(void *pParam)
            {
            char Buffer[BUFSIZE];
            int Len;
            sockaddr_in from;
            SOCKET msg_socket;
            int fromlen,retval;
            SocketPair SPair;
            ProxyParam ProxyP;
            CWinThread *pChildThread;
            fromlen=sizeof(from);
            msg_socket=accept(gListen_Socket,(struct sockaddr*)&from,&fromlen);
            AfxBeginThread(UserToProxyThread,pParam); //啟動另一偵聽.
            if( msg_socket==INVALID_SOCKET)
            { printf( "\nError in accept "); return -5;}
            //讀客戶的第一行數(shù)據(jù)


            SPair.IsUser_ProxyClosed=FALSE;
            SPair.IsProxy_ServerClosed=TRUE;
            SPair.user_proxy=msg_socket;


            retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);


            if(retval==SOCKET_ERROR)
            { printf("\nError Recv");
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            }
            if(retval==0)
            {printf("Client Close connection\n");
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            }
            Len=retval;
            #ifdef _DEBUG


            Buffer[Len]=0;
            printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
            #endif
            //
            SPair.IsUser_ProxyClosed=FALSE;
            SPair.IsProxy_ServerClosed=TRUE;
            SPair.user_proxy=msg_socket;


            ProxyP.pPair=&SPair;
            ProxyP.User_SvrOK=CreateEvent(NULL,TRUE,FALSE,NULL);


            GetAddressAndPort( Buffer,ProxyP.Address,&ProxyP.Port);


            pChildThread=AfxBeginThread(ProxyToServer,(LPVOID)&ProxyP);

            ::WaitForSingleObject(ProxyP.User_SvrOK,60000); //等待聯(lián)結(jié)
            ::CloseHandle(ProxyP.User_SvrOK);


            while(SPair.IsProxy_ServerClosed ==FALSE && SPair.IsUser_ProxyClosed==FALSE)

            {
            retval=send(SPair.proxy_server,Buffer,Len,0);
            if(retval==SOCKET_ERROR)
            { printf("\n send() failed:error%d\n",WSAGetLastError());
            if(SPair.IsProxy_ServerClosed==FALSE)
            {
            closesocket(SPair.proxy_server);
            SPair.IsProxy_ServerClosed=TRUE;
            }
            continue;
            }
            retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);


            if(retval==SOCKET_ERROR)
            { printf("\nError Recv");
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            continue;
            }
            if(retval==0)
            {printf("Client Close connection\n");
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            break;
            }
            Len=retval;
            #ifdef _DEBUG
            Buffer[Len]=0;
            printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
            #endif


            } //End While


            if(SPair.IsProxy_ServerClosed==FALSE)
            {
            closesocket(SPair.proxy_server);
            SPair.IsProxy_ServerClosed=TRUE;
            }
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            ::WaitForSingleObject(pChildThread- >m_hThread,20000); //Should check the return value
            return 0;
            }


            // 讀取遠(yuǎn)程主機(jī)數(shù)據(jù),并發(fā)往本地客戶機(jī)
            UINT ProxyToServer(LPVOID pParam){
            ProxyParam * pPar=(ProxyParam*)pParam;
            char Buffer[BUFSIZE];
            char *server_name= "localhost";
            unsigned short port ;
            int retval,Len;
            unsigned int addr;

            int socket_type ;
            struct sockaddr_in server;
            struct hostent *hp;
            SOCKET conn_socket;


            socket_type = SOCK_STREAM;
            server_name = pPar- >Address;
            port = pPar- >Port;


            if (isalpha(server_name[0])) { /* server address is a name */

            hp = gethostbyname(server_name);
            }
            else { /* Convert nnn.nnn address to a usable one */
            addr = inet_addr(server_name);
            hp = gethostbyaddr((char *)&addr,4,AF_INET);
            }
            if (hp == NULL ) {
            fprintf(stderr,"Client: Cannot resolve address [%s]: Error %d\n",
            server_name,WSAGetLastError());
            ::SetEvent(pPar- >User_SvrOK);
            return 0;
            }


            //
            // Copy the resolved information into the sockaddr_in structure
            //
            memset(&server,0,sizeof(server));
            memcpy(&(server.sin_addr),hp- >h_addr,hp- >h_length);
            server.sin_family = hp- >h_addrtype;
            server.sin_port = htons(port);


            conn_socket = socket(AF_INET,socket_type,0); /* 打開一個 socket */
            if (conn_socket < 0 ) {
            fprintf(stderr,"Client: Error Opening socket: Error %d\n",
            WSAGetLastError());
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            ::SetEvent(pPar- >User_SvrOK);
            return -1;
            }


            #ifdef _DEBUG
            printf("Client connecting to: %s\n",hp- >h_name);
            #endif
            if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server))
            == SOCKET_ERROR) {
            fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            ::SetEvent(pPar- >User_SvrOK);
            return -1;
            }
            pPar- >pPair- >proxy_server=conn_socket;
            pPar- >pPair- >IsProxy_ServerClosed=FALSE;

            ::SetEvent(pPar- >User_SvrOK);
            // cook up a string to send
            while(!pPar- >pPair- >IsProxy_ServerClosed &&!pPar- >pPair- >IsUser_ProxyClosed)
            {
            retval = recv(conn_socket,Buffer,sizeof (Buffer),0 );
            if (retval == SOCKET_ERROR ) {
            fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());

            closesocket(conn_socket);
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            break;
            }
            Len=retval;
            if (retval == 0) {
            printf("Server closed connection\n");
            closesocket(conn_socket);
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            break;
            }


            retval = send(pPar- >pPair- >user_proxy,Buffer,Len,0);
            if (retval == SOCKET_ERROR) {
            fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
            closesocket(pPar- >pPair- >user_proxy);
            pPar- >pPair- >IsUser_ProxyClosed=TRUE;
            break;
            }
            #ifdef _DEBUG
            Buffer[Len]=0;
            printf("Received %d bytes, data [%s] from server\n",retval,Buffer);
            #endif
            }
            if(pPar- >pPair- >IsProxy_ServerClosed==FALSE)
            {
            closesocket(pPar- >pPair- >proxy_server);
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            }
            if(pPar- >pPair- >IsUser_ProxyClosed==FALSE)
            {closesocket(pPar- >pPair- >user_proxy);
            pPar- >pPair- >IsUser_ProxyClosed=TRUE;
            }
            return 1;
            }





            int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
            {
            int nRetCode = 0;


            // 初始化SOCKET
            if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
            {
            // 錯誤處理
            cerr < < _T("Fatal Error: MFC initialization failed") < < endl;
            nRetCode = 1;

            }
            else
            {
            // 主程序開始.
            StartServer();
            while(1)
            if(getchar()=='q') break;
            CloseServer();
            }


            return nRetCode;
            }
            #ifdef _DEBUG
            printf("Client connecting to: %s\n",hp- >h_name);
            #endif
            if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server))
            == SOCKET_ERROR) {
            fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());

            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            ::SetEvent(pPar- >User_SvrOK);
            return -1;
            }
            pPar- >pPair- >proxy_server=conn_socket;
            pPar- >pPair- >IsProxy_ServerClosed=FALSE;
            ::SetEvent(pPar- >User_SvrOK);
            // cook up a string to send
            while(!pPar- >pPair- >IsProxy_ServerClosed &&!pPar- >pPair- >IsUser_ProxyClosed)
            {
            retval = recv(conn_socket,Buffer,sizeof (Buffer),0 );
            if (retval == SOCKET_ERROR ) {
            fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());
            closesocket(conn_socket);
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            break;
            }
            Len=retval;
            if (retval == 0) {
            printf("Server closed connection\n");
            closesocket(conn_socket);
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            break;
            }


            retval = send(pPar- >pPair- >user_proxy,Buffer,Len,0);
            if (retval == SOCKET_ERROR) {
            fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
            closesocket(pPar- >pPair- >user_proxy);
            pPar- >pPair- >IsUser_ProxyClosed=TRUE;
            break;
            }
            #ifdef _DEBUG
            Buffer[Len]=0;
            printf("Received %d bytes, data [%s] from server\n",retval,Buffer);
            #endif
            }
            if(pPar- >pPair- >IsProxy_ServerClosed==FALSE)

            {
            closesocket(pPar- >pPair- >proxy_server);
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            }
            if(pPar- >pPair- >IsUser_ProxyClosed==FALSE)
            {closesocket(pPar- >pPair- >user_proxy);
            pPar- >pPair- >IsUser_ProxyClosed=TRUE;
            }
            return 1;
            }





            int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
            {
            int nRetCode = 0;


            // 初始化SOCKET
            if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
            {
            // 錯誤處理
            cerr < < _T("Fatal Error: MFC initialization failed") < < endl;
            nRetCode = 1;
            }
            else
            {
            // 主程序開始.
            StartServer();
            while(1)
            if(getchar()=='q') break;
            CloseServer();
            }


            return nRetCode;
            }
              回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2008-10-21 02:22 聶文龍
            打造自己的HTTP代理服務(wù)器
            #include "stdafx.h"
            #include "HTTPPROXY.h"
            #define FD_NOEVENT 0
            //
            #define BACKUP 100
            #define MAXDATALEN 65535
            int HttpListenPort;
            SOCKET HttpListenSock;
            //
            typedef struct _CLIENTINFO{
            SOCKET clientsock;
            SOCKET udpsock;
            sockaddr_in clientsock_addr;
            }CLIENTINFO,*LPCLIENTINFO;
            CLIENTINFO HttpClientInfo;
            //
            typedef struct _SOCKINFO{
            SOCKET sourcesock;
            SOCKET destsock;
            }SOCKINFO,*LPSOCKINFO;
            SOCKINFO httpsockinfo;
            //
            extern long GetSocketEventId(SOCKET remotesock);
            extern unsigned long GetLocalIp();
            extern unsigned long GetDomainIp(char domainname[250]);
            /*
            long GetSocketEventId(SOCKET remotesock){
            long EventId;
            HANDLE hevent;
            hevent=CreateEvent(NULL,0,0,0);
            WSANETWORKEVENTS socket_events;
            EventId=FD_NOEVENT;
            if(WSAEventSelect(remotesock,hevent,FD_ACCEPT|FD_CONNECT|FD_
            READ|FD_WRITE|FD_CLOSE)==SOCKET_ERROR) return EventId;
            WSAEnumNetworkEvents(remotesock,hevent,&socket_events);
            if(socket_events.lNetworkEvents!=0){
            switch(socket_events.lNetworkEvents){
            case FD_ACCEPT:EventId=FD_ACCEPT;break;
            case FD_CONNECT:EventId=FD_CONNECT;break;
            case FD_READ:EventId=FD_READ;break;
            case FD_WRITE:EventId=FD_WRITE;break;
            case FD_CLOSE:EventId=FD_CLOSE;break;
            case FD_OOB:EventId=FD_OOB;break;
            default:EventId=FD_NOEVENT;break;
            }
            }
            else EventId=FD_NOEVENT;
            return EventId;
            }
            //
            unsigned long GetLocalIp()
            {
            char IP[MAX_PATH],*ip;
            char pc_name[80];
            struct in_addr in;
            struct hostent *host;
            WORD wVersionRequested;
            WSADATA wsaData;
            wVersionRequested=MAKEWORD(2,0);
            ip=IP;
            strcpy(ip,"Ip not get!");
            if(WSAStartup(wVersionRequested,&wsaData)) return 0;
            if(gethostname(pc_name,80)==SOCKET_ERROR){
            WSACleanup();
            return 0;
            }
            if(!(host=gethostbyname(pc_name))){
            WSACleanup();
            return 0;
            }
            in.s_addr=*((unsigned long *)host->h_addr_list[0]);
            strcpy(ip,inet_ntoa(in));
            WSACleanup();
            return in.s_addr;
            }
            //
            unsigned long GetDomainIp(char domainname[250])
            {
            char IP[MAX_PATH],*ip;
            struct in_addr in;
            struct hostent *host;
            WORD wVersionRequested;
            WSADATA wsaData;
            wVersionRequested=MAKEWORD(2,0);
            ip=IP;
            strcpy(ip,"Ip not get!");
            if(WSAStartup(wVersionRequested,&wsaData)) return 0;
            if(!(host=gethostbyname(domainname))){
            WSACleanup();
            return 0;
            }
            in.s_addr=*((unsigned long *)host->h_addr_list[0]);
            strcpy(ip,inet_ntoa(in));
            WSACleanup();
            return in.s_addr;
            }
            */
            //
            //
            UINT HttpReciveThread(LPVOID info){ //針對客戶端的接收處理線程
            LPSOCKINFO psockinfo;
            SOCKET sourcesock,destsock;
            char data[MAXDATALEN];
            long eventid;
            int datalen;
            psockinfo=(LPSOCKINFO)info;
            sourcesock=psockinfo->sourcesock;
            destsock=psockinfo->destsock;
            TRACE("deail recive thread ok!\r\n");
            while(true){
            eventid=GetSocketEventId(sourcesock);
            switch(eventid){
            case FD_CLOSE:
            TRACE("s fdclosed\r\n");
            closesocket(destsock);
            return 1;
            break;
            default:break;
            }
            eventid=GetSocketEventId(destsock);
            switch(eventid){
            case FD_CLOSE:
            closesocket(sourcesock);
            TRACE("d fdclosed\r\n");
            return 1;
            break;
            default:break;
            }
            datalen=recv(sourcesock,data,sizeof(data),0);
            if(datalen==0){
            closesocket(sourcesock);
            closesocket(destsock);
            TRACE("s fdclosed\r\n");
            break;
            }
            if(datalen>0){
            while(!send(destsock,data,datalen,0));
            }
            Sleep(1);
            }
            return 1;
            }
            //
            UINT HttpSendThread(LPVOID info){ //針對遠(yuǎn)程端的接收處理線程
            LPSOCKINFO psockinfo;
            SOCKET sourcesock,destsock;
            char data[MAXDATALEN];
            long eventid;
            int datalen;
            psockinfo=(LPSOCKINFO)info;
            sourcesock=psockinfo->sourcesock;
            destsock=psockinfo->destsock;
            TRACE("deail send thread ok!\r\n");
            while(true){
            eventid=GetSocketEventId(sourcesock);
            switch(eventid){
            case FD_CLOSE:
            TRACE("s fdclosed\r\n");
            closesocket(destsock);
            return 1;
            break;
            default:break;
            }
            eventid=GetSocketEventId(destsock);
            switch(eventid){
            case FD_CLOSE:
            closesocket(sourcesock);
            TRACE("d fdclosed\r\n");
            return 1;
            break;
            default:break;
            }
            datalen=recv(destsock,data,sizeof(data),0);
            if(datalen==0){
            closesocket(sourcesock);
            closesocket(destsock);
            TRACE("d fdclosed\r\n");
            break;
            }
            if(datalen>0){
            while(!send(sourcesock,data,datalen,0));
            }
            Sleep(1);
            }
            return 1;
            }
            //
            //
            UINT HttpProxyServerThread(LPVOID info){ //針對一次服務(wù)的線程
            LPCLIENTINFO pclientinfo;
            SOCKET connectsock,clientsock;
            sockaddr_in remotesock_addr;
            char data[MAXDATALEN],url[250],temp[250],httpurl[250],portnum[10];
            int datalen,i,index_start,index_end,port;
            CString HttpString,UrlString,PortString;
            pclientinfo=(LPCLIENTINFO)info;
            clientsock=pclientinfo->clientsock;
            ZeroMemory((void *)data,sizeof(data));
            datalen=recv(clientsock,data,sizeof(data),0);
            if(datalen<=0){
            closesocket(clientsock);
            return 0;
            }
            HttpString.Format("%s",data);
            UrlString=HttpString;
            TRACE("get http string:\r\n");
            TRACE(HttpString);
            index_start=HttpString.Find("Host: ",0); //尋找url標(biāo)記
            if(index_start<=0){
            closesocket(clientsock);
            return 0;
            }
            index_end=HttpString.Find("\r\n",index_start);
            if(index_end<=0){
            closesocket(clientsock);
            return 0;
            }
            UrlString=HttpString.Mid(index_start+6,index_end-index_start-6); //讀取 url字符串
            TRACE("\r\n get url:");
            TRACE(UrlString);
            wsprintf(url,"%s",UrlString);
            strcpy(temp,url);
            strcat(temp,":");
            datalen=strlen(temp);
            if(HttpString.Find("GET",0)==0){ //判斷get命令,并處理
            index_start=HttpString.Find(temp,0);
            strcpy(httpurl,"http://");
            if(index_start>0){
            index_end=HttpString.Find("/",index_start);
            if(index_end<=0){
            closesocket(clientsock);
            return 0;
            }
            PortString=HttpString.Mid(index_start+datalen,index_end-index_start-datalen);
            port=atoi(PortString);
            strcat(httpurl,temp);
            itoa(port,portnum,sizeof(portnum));
            strcat(httpurl,portnum);
            strcat(httpurl,"/");
            }
            else{
            port=80;
            strcat(httpurl,url);
            strcat(httpurl,"/");
            }
            TRACE("get http url:%s\r\n",httpurl);
            HttpString.Replace(httpurl,"/");
            HttpString.Replace("Proxy-","");
            HttpString.Replace("HTTP/1.0","HTTP/1.1");
            }
            else if(HttpString.Find("CONNECT",0)==0){ //判斷connect命令并處理
            index_start=HttpString.Find(temp,0);
            if(index_start>0){
            index_end=HttpString.Find(" ",index_start);
            if(index_end<=0){
            closesocket(clientsock);
            return 0;
            }
            PortString=HttpString.Mid(index_start+datalen,index_end-index_start-datalen);
            port=atoi(PortString);
            }
            else{
            closesocket(clientsock);
            return 0;
            }
            }
            TRACE("get new http string:\r\n");
            TRACE(HttpString);
            remotesock_addr.sin_family=AF_INET;
            remotesock_addr.sin_port=htons(port);
            remotesock_addr.sin_addr.S_un.S_addr=GetDomainIp(url);
            connectsock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
            if(connect(connectsock,(const sockaddr *)&remotesock_addr,sizeof(remotesock_addr))==INVALID_SOCKET){ //連接遠(yuǎn)程主機(jī)
            closesocket(clientsock);
            return 0;
            }
            TRACE("\r\nconnect to remote ip ok\r\n");
            ZeroMemory((void *)data,sizeof(data));
            wsprintf(data,"%s",HttpString);
            datalen=strlen(data);
            if(HttpString.Find("CONNECT",0)<0) while(!send(connectsock,data,datalen,0));
            else{
            strcpy(data,"HTTP/1.0 200 Connection established\r\nProxy-agent: CHTTPPROXY V1.0 powered by shadow\r\n\r\n");
            datalen=strlen(data);
            while(!send(clientsock,data,datalen,0));
            }
            httpsockinfo.sourcesock=clientsock;
            httpsockinfo.destsock=connectsock;
            AfxBeginThread(HttpReciveThread,(LPVOID)&httpsockinfo); //拋出處理線程
            AfxBeginThread(HttpSendThread,(LPVOID)&httpsockinfo); //
            Sleep(100);
            return 1;
            }
            //
            UINT StartHttpProxy(LPVOID info){ //端口監(jiān)聽線程
            SOCKET NewSock;
            int socklen;
            sockaddr_in serversock,remotesock_addr;
            serversock.sin_family=AF_INET;
            serversock.sin_addr.S_un.S_addr=INADDR_ANY;
            serversock.sin_port=htons(HttpListenPort);
            HttpListenSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
            if(HttpListenSock==INVALID_SOCKET) return 0;
            if(bind(HttpListenSock,(const sockaddr *)&serversock,
            sizeof(serversock))==SOCKET_ERROR) return 0;
            listen(HttpListenSock,BACKUP);
            socklen=sizeof(remotesock_addr);
            TRACE("start http proxy thread while\r\n");
            while(true){
            NewSock=accept(HttpListenSock,(sockaddr *)&remotesock_addr,&socklen);
            TRACE("waitting ok...\r\n");
            if(NewSock==INVALID_SOCKET){
            Sleep(1);
            continue;
            }
            ZeroMemory((void *)&HttpClientInfo,sizeof(CLIENTINFO));
            HttpClientInfo.clientsock=NewSock;
            HttpClientInfo.clientsock_addr=remotesock_addr;
            TRACE("start proxy thread\r\n");
            AfxBeginThread(HttpProxyServerThread,(LPVOID)&HttpClientInfo);
            Sleep(100);
            }
            return 1;
            }
            //
            CHTTPPROXY::CHTTPPROXY()
            {
            WSADATA WsaData;
            WORD wsaVer;
            wsaVer=MAKEWORD(2,0);
            WsaStartupOk=false;
            if(WSAStartup(wsaVer,&WsaData)!=SOCKET_ERROR) WsaStartupOk=true;
            }

            CHTTPPROXY::~CHTTPPROXY()
            {
            if(WsaStartupOk){
            WSACleanup();
            }
            }

            int CHTTPPROXY::StartProxy(int listenport)
            {
            HttpListenPort=listenport;
            AfxBeginThread(StartHttpProxy,(LPVOID)NULL);
            return 1;
            }


            /*=========================================================
            FILE:HTTPPROXY.h
            ==========================================================*/
            class CHTTPPROXY
            {
            public:
            int StartProxy(int listenport);
            bool WsaStartupOk;
            CHTTPPROXY();
            virtual ~CHTTPPROXY();

            };

            /*==================================================
            FILE:stdafx.h
            ===================================================*/
            #include
            #include
            #include
            #include


            注:不要忘了在link選項中添加wsock32.lib和ws2_32.lib,或在文件前部加上如下語句:
            #paragma comment(lib,"wsock32.lib")
            #paragma comment(lib,"ws2_32.lib")

            本代碼在win2k和vc6.0下編譯成功~~
            用法,把這幾個文件添加到你的項目中,在WinMain()中添加如下代碼:
            CHTTPPROXY httpproxy;
            httpproxy.StartProxy(7890);
            有問題mailto me!


              回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2008-10-21 02:23 聶文龍
            VC++6實現(xiàn)簡單的代理服務(wù)器

            本文轉(zhuǎn)自CSDN的blog:http://blog.csdn.net/snaill/archive/2006/03/14/624437.aspx

            #include "stdafx.h"
            #include "Proxy.h"
            #include < winsock2.h > //WINSOCKET API 2。0
            #include < stdlib.h >
            #include < stdio.h >
            #include < string.h >

            #ifdef _DEBUG
            #define new DEBUG_NEW
            #undef THIS_FILE
            static char THIS_FILE[] = __FILE__;
            #endif

            /////////////////////////////////////////////////////////////////////////////


            #define HTTP "http://"
            #define FTP "ftp://"
            #define PROXYPORT 5001 //Proxy 端口
            #define BUFSIZE 10240 //緩沖區(qū)大小


            CWinApp theApp;

            using namespace std;

            UINT ProxyToServer(LPVOID pParam);
            UINT UserToProxyThread(void *pParam);

            struct SocketPair{
            SOCKET user_proxy; //socket : 本地機(jī)器到PROXY 服務(wù)機(jī)
            SOCKET proxy_server; //socket : PROXY 服務(wù)機(jī)到遠(yuǎn)程主機(jī)
            BOOL IsUser_ProxyClosed; // 本地機(jī)器到PROXY 服務(wù)機(jī)狀態(tài)
            BOOL IsProxy_ServerClosed; // PROXY 服務(wù)機(jī)到遠(yuǎn)程主機(jī)狀態(tài)
            };


            struct ProxyParam{
            char Address[256]; // 遠(yuǎn)程主機(jī)地址
            HANDLE User_SvrOK; // PROXY 服務(wù)機(jī)到遠(yuǎn)程主機(jī)的聯(lián)結(jié)狀態(tài)
            SocketPair *pPair; // 維護(hù)一組SOCKET的指針
            int Port; // 用來聯(lián)結(jié)遠(yuǎn)程主機(jī)的端口
            }; //這個結(jié)構(gòu)用來PROXY SERVER與遠(yuǎn)程主機(jī)的信息交換.

            SOCKET gListen_Socket; //用來偵聽的SOCKET。

            int StartServer() //啟動服務(wù)
            {
            WSADATA wsaData;
            sockaddr_in local;
            SOCKET listen_socket;

            if(::WSAStartup(0x202,&wsaData)!=0)
            {printf("\nError in Startup session.\n");WSACleanup();return -1;};

            local.sin_family=AF_INET;
            local.sin_addr.s_addr=INADDR_ANY;
            local.sin_port=htons(PROXYPORT);

            listen_socket=socket(AF_INET,SOCK_STREAM,0);
            if(listen_socket==INVALID_SOCKET)
            {printf("\nError in New a Socket.");WSACleanup();return -2;}

            if(::bind(listen_socket,(sockaddr *)&local,sizeof(local))!=0)
            {printf("\n Error in Binding socket."); WSACleanup();return -3; };

            if(::listen(listen_socket,5)!=0)
            {printf("\n Error in Listen."); WSACleanup(); return -4;}
            gListen_Socket=listen_socket;
            AfxBeginThread(UserToProxyThread,NULL); //啟動偵聽
            return 1;
            }

            int CloseServer() //關(guān)閉服務(wù)
            {
            closesocket(gListen_Socket);
            WSACleanup();
            return 1;
            }
            //分析接收到的字符,得到遠(yuǎn)程主機(jī)地址

            int GetAddressAndPort( char * str, char *address, int * port)
            {
            char buf[BUFSIZE], command[512], proto[128], *p;
            int j;
            sscanf(str,"%s%s%s",command,buf,proto);
            p=strstr(buf,HTTP);
            //HTTP
            if(p)
            {
            p+=strlen(HTTP);
            for(int i=0;i< strlen(p);i++)
            if( *(p+i)=='/') break;
            *(p+i)=0;
            strcpy(address,p);
            p=strstr(str,HTTP);
            for(int j=0;j< i+strlen(HTTP);j++)
            *(p+j)=' '; //去掉遠(yuǎn)程主機(jī)名: GET http:/www.csdn.net/ HTTP1.1 == > GET / HTTP1.1
            *port=80; //缺省的 http 端口
            }
            else
            {//FTP, 不支持, 下面的代碼可以省略.
            p=strstr(buf,FTP);
            if(!p) return 0;
            p+=strlen(FTP);
            for(int i=0;i< strlen(p);i++)
            if( *(p+i)=='/') break; //Get The Remote Host
            *(p+i)=0;
            for(j=0;j< strlen(p);j++)
            if(*(p+j)==':')
            {*port=atoi(p+j+1); //Get The Port
            *(p+j)=0;
            }
            else *port=21;

            strcpy(address,p);
            p=strstr(str,FTP);
            for(j=0;j< i+strlen(FTP);j++)
            *(p+j)=' ';
            }
            return 1;
            }

            // 取到本地的數(shù)據(jù),發(fā)往遠(yuǎn)程主機(jī)
            UINT UserToProxyThread(void *pParam)
            {
            char Buffer[BUFSIZE];
            int Len;
            sockaddr_in from;
            SOCKET msg_socket;
            int fromlen,retval;
            SocketPair SPair;
            ProxyParam ProxyP;
            CWinThread *pChildThread;
            fromlen=sizeof(from);
            msg_socket=accept(gListen_Socket,(struct sockaddr*)&from,&fromlen);
            AfxBeginThread(UserToProxyThread,pParam); //啟動另一偵聽.
            if( msg_socket==INVALID_SOCKET)
            { printf( "\nError in accept "); return -5;}
            //讀客戶的第一行數(shù)據(jù)

            SPair.IsUser_ProxyClosed=FALSE;
            SPair.IsProxy_ServerClosed=TRUE;
            SPair.user_proxy=msg_socket;

            retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);

            if(retval==SOCKET_ERROR)
            { printf("\nError Recv");
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            }
            if(retval==0)
            {printf("Client Close connection\n");
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            }
            Len=retval;
            #ifdef _DEBUG

            Buffer[Len]=0;
            printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
            #endif
            //
            SPair.IsUser_ProxyClosed=FALSE;
            SPair.IsProxy_ServerClosed=TRUE;
            SPair.user_proxy=msg_socket;

            ProxyP.pPair=&SPair;
            ProxyP.User_SvrOK=CreateEvent(NULL,TRUE,FALSE,NULL);

            GetAddressAndPort( Buffer,ProxyP.Address,&ProxyP.Port);

            pChildThread=AfxBeginThread(ProxyToServer,(LPVOID)&ProxyP);
            ::WaitForSingleObject(ProxyP.User_SvrOK,60000); //等待聯(lián)結(jié)
            ::CloseHandle(ProxyP.User_SvrOK);

            while(SPair.IsProxy_ServerClosed ==FALSE && SPair.IsUser_ProxyClosed==FALSE)
            {
            retval=send(SPair.proxy_server,Buffer,Len,0);
            if(retval==SOCKET_ERROR)
            { printf("\n send() failed:error%d\n",WSAGetLastError());
            if(SPair.IsProxy_ServerClosed==FALSE)
            {
            closesocket(SPair.proxy_server);
            SPair.IsProxy_ServerClosed=TRUE;
            }
            continue;
            }
            retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);

            if(retval==SOCKET_ERROR)
            { printf("\nError Recv");
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            continue;
            }
            if(retval==0)
            {printf("Client Close connection\n");
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            break;
            }
            Len=retval;
            #ifdef _DEBUG
            Buffer[Len]=0;
            printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
            #endif

            } //End While

            if(SPair.IsProxy_ServerClosed==FALSE)
            {
            closesocket(SPair.proxy_server);
            SPair.IsProxy_ServerClosed=TRUE;
            }
            if(SPair.IsUser_ProxyClosed==FALSE)
            {closesocket(SPair.user_proxy);
            SPair.IsUser_ProxyClosed=TRUE;
            }
            ::WaitForSingleObject(pChildThread- >m_hThread,20000); //Should check the return value
            return 0;
            }
            // 讀取遠(yuǎn)程主機(jī)數(shù)據(jù),并發(fā)往本地客戶機(jī)
            UINT ProxyToServer(LPVOID pParam){
            ProxyParam * pPar=(ProxyParam*)pParam;
            char Buffer[BUFSIZE];
            char *server_name= "localhost";
            unsigned short port ;
            int retval,Len;
            unsigned int addr;
            int socket_type ;
            struct sockaddr_in server;
            struct hostent *hp;
            SOCKET conn_socket;

            socket_type = SOCK_STREAM;
            server_name = pPar- >Address;
            port = pPar- >Port;

            if (isalpha(server_name[0])) { /* server address is a name */
            hp = gethostbyname(server_name);
            }
            else { /* Convert nnn.nnn address to a usable one */
            addr = inet_addr(server_name);
            hp = gethostbyaddr((char *)&addr,4,AF_INET);
            }
            if (hp == NULL ) {
            fprintf(stderr,"Client: Cannot resolve address [%s]: Error %d\n",
            server_name,WSAGetLastError());
            ::SetEvent(pPar- >User_SvrOK);
            return 0;
            }

            //
            // Copy the resolved information into the sockaddr_in structure
            //
            memset(server,0,sizeof(server));
            memcpy(&(server.sin_addr),hp- >h_addr,hp- >h_length);
            server.sin_family = hp- >h_addrtype;
            server.sin_port = htons(port);

            conn_socket = socket(AF_INET,socket_type,0); /* 打開一個 socket */
            if (conn_socket < 0 ) {
            fprintf(stderr,"Client: Error Opening socket: Error %d\n",
            WSAGetLastError());
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            ::SetEvent(pPar- >User_SvrOK);
            return -1;
            }
            #ifdef _DEBUG
            printf("Client connecting to: %s\n",hp- >h_name);
            #endif
            if (connect(conn_socket,(struct sockaddr*)server,sizeof(server))
            == SOCKET_ERROR) {
            fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            ::SetEvent(pPar- >User_SvrOK);
            return -1;
            }
            pPar- >pPair- >proxy_server=conn_socket;
            pPar- >pPair- >IsProxy_ServerClosed=FALSE;
            ::SetEvent(pPar- >User_SvrOK);
            // cook up a string to send
            while(!pPar- >pPair- >IsProxy_ServerClosed &&!pPar- >pPair- >IsUser_ProxyClosed)
            {
            retval = recv(conn_socket,Buffer,sizeof (Buffer),0 );
            if (retval == SOCKET_ERROR ) {
            fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());
            closesocket(conn_socket);
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            break;
            }
            Len=retval;
            if (retval == 0) {
            printf("Server closed connection\n");
            closesocket(conn_socket);
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            break;
            }

            retval = send(pPar- >pPair- >user_proxy,Buffer,Len,0);
            if (retval == SOCKET_ERROR) {
            fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
            closesocket(pPar- >pPair- >user_proxy);
            pPar- >pPair- >IsUser_ProxyClosed=TRUE;
            break;
            }
            #ifdef _DEBUG
            Buffer[Len]=0;
            printf("Received %d bytes, data [%s] from server\n",retval,Buffer);
            #endif
            }
            if(pPar- >pPair- >IsProxy_ServerClosed==FALSE)
            {
            closesocket(pPar- >pPair- >proxy_server);
            pPar- >pPair- >IsProxy_ServerClosed=TRUE;
            }
            if(pPar- >pPair- >IsUser_ProxyClosed==FALSE)
            {closesocket(pPar- >pPair- >user_proxy);
            pPar- >pPair- >IsUser_ProxyClosed=TRUE;
            }
            return 1;
            }



            int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
            {
            int nRetCode = 0;

            // 初始化SOCKET
            if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
            {
            // 錯誤處理
            cerr < < _T("Fatal Error: MFC initialization failed") < < endl;
            nRetCode = 1;
            }
            else
            {
            // 主程序開始.
            StartServer();
            while(1)
            if(getchar()=='q') break;
            CloseServer();
            }

            return nRetCode;
            }   回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2008-10-21 02:25 聶文龍
            通過Socket5代理服務(wù)器訪問網(wǎng)絡(luò)的問題
            SOCKS5

            Socks5版本的協(xié)議說明參考 RFC1928,RFC1929
            下面簡單地羅列程序?qū)崿F(xiàn),不涉及詳細(xì)的協(xié)議規(guī)范。首先對于TCP連接,然后再討論UDP傳輸。至于通過socks5的多播通訊,有興趣可以參考D. Chouinard的文章。

            1、TCP:

            // 建立流套接字
            SOCKET m_socTCP=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

            // 連接到代理服務(wù)器
            int nRet = connect(m_socTCP,(SOCKADDR*)&m_saiProxy,sizeof(m_saiProxy));

            // Step 1: 連接代理服務(wù)器成功后,馬上開始和代理協(xié)商,協(xié)商報文如下,詢問服務(wù)器,版本5,是需要驗證(0x02)還是不需要驗證(0x00)
              +------+-------------------+------------+
              |VER | Number of METHODS | METHODS |
              +------+-------------------+------------+
              | 0x05 | 0x02 (有兩個方法) | 0x00 | 0x02|
              +------+-------------------+------------+
            const char reqNego[4]={(char)0x05,(char)0x02,(char)0x00,(char)0x02};
            nRet = send(m_socTCP,reqNego,4,0);

            // Setp 2: 代理服務(wù)器將返回兩個字節(jié)的協(xié)商結(jié)果,接收協(xié)商結(jié)果
            fd_set fdread;FD_ZERO(&fdread);
            FD_SET(m_socTCP,&fdread);
            // Last param set to NULL for blocking operation. (struct timeval*)
            if((nRet=select(0,&fdread,NULL,NULL,NULL))==SOCKET_ERROR){return NC_E_PROXY_SELECT_READ|WSAGetLastError();}
            char resNego[2]={'\0'};
            int nRcvd=0,nCount=0;
            while(1)
            {
            if(FD_ISSET(m_socTCP,&fdread))
            {
            //接收sock[0]發(fā)送來的數(shù)據(jù)
            do{
            nRet = recv(m_socTCP, (char*)resNego+nRcvd, 2-nRcvd,0);
            if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            nRcvd += nRet;
            }
            while((nRcvd!=2)&&(++nCount<1000));
            if(nRcvd==2) break;
            }
            if(nCount++>=2000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            }
            if(resNego[0]!=0x05 || (resNego[1]!=0x00 && resNego[1]!=0x02)){return NC_E_PROXY_PROTOCOL_VERSION|WSAGetLastError();};

            // Step 3: 根據(jù)協(xié)商結(jié)果判斷是否需要驗證用戶,如果是0x02,則需要提供驗證,驗證部分參考RFC1929
            if(resNego[1]==0x02)
            {
            // 需要密碼驗證
            char reqAuth[513]={'\0'};
            BYTE byLenUser = (BYTE)strlen(m_szProxyUserName);
            BYTE byLenPswd = (BYTE)strlen(m_szProxyPassword);
            reqAuth[0]=0x01;
            reqAuth[1]=byLenUser;
            sprintf(&reqAuth[2],"%s",m_szProxyUserName);
            reqAuth[2+byLenUser]=byLenPswd;
            sprintf(&reqAuth[3+byLenUser],"%s",m_szProxyPassword);
            //Send authentication info
            int len = (int)byLenUser + (int)byLenPswd + 3;
            nRet=send(m_socTCP,(const char*)reqAuth,len,0);
            if (nRet==SOCKET_ERROR){return NC_E_PROXY_SEND|WSAGetLastError();}
            //Now : Response to the auth request
            char resAuth[2]={'\0'};
            int nRcvd=0,nCount=0;
            do{
            nRet = recv(m_socTCP,resAuth+nRcvd,2-nRcvd,0);
            if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            nRcvd += nRet;
            }
            while((nRcvd!=2)&&(++nCount<1000));
            if(nCount>=1000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            if (resAuth[1]!=0) return NC_E_PROXY_AUTHORIZE;
            // 密碼驗證通過了
            }

            // Step 4: 協(xié)商完成,開始發(fā)送連接遠(yuǎn)程服務(wù)器請求,請求報文格式如下:
              +----+-----+-------+------+----------+----------+
              |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
              +----+-----+-------+------+----------+----------+
              | 1 |  1 | 0x00 |  1 | Variable |   2   |
              +----+-----+-------+------+----------+----------+
            // CMD==0x01 表示連接, ATYP==0x01表示采用IPV4格式地址,DST.ADDR是遠(yuǎn)程服務(wù)器地址,DST.PORT是遠(yuǎn)程服務(wù)器端口
            // 如果需要接受外來連接,則需要在連接完成之后,發(fā)送CMD==0x02綁定請求,代理將為此請求綁定一個套接字接受外部連接
            char reqSubNego[10]={(char)0x05,(char)0x01,(char)0x00,(char)0x01,(char)0x00,(char)0x00,(char)0x00,(char)0x00,(char)0x00,(char)0x00};
            *(unsigned long*)&reqSubNego[4] =m_saiServerTCP.sin_addr.S_un.S_addr;
            *(unsigned short*)&reqSubNego[8]=m_saiServerTCP.sin_port;
            nRet=send(m_socTCP,(const char*)reqSubNego,10,0);
            if (nRet==SOCKET_ERROR){return NC_E_PROXY_SEND|WSAGetLastError();}

            // Step 5: 接收對請求的響應(yīng),響應(yīng)包格式如下
              +----+-----+-------+------+----------+----------+
              |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
              +----+-----+-------+------+----------+----------+
              | 1 | 1 | 0x00 | 1   | Variable |   2   |
              +----+-----+-------+------+----------+----------+
            // VER 必須是0x05, REP==0x00表示成功,ATYP==0x01表示地址是IPV4地址,BND.ADDR 是代理為連接遠(yuǎn)程服務(wù)器綁定的地址,BND.PORT是這個套接字的端口
            char resSubNego1[5]={'\0'};
            if(FD_ISSET(m_socTCP,&fdread))
            {
            int nRcvd=0,nCount=0;
            do{
            nRet = recv(m_socTCP,resSubNego1+nRcvd,5-nRcvd,0);
            if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            nRcvd += nRet;
            }
            while((nRcvd!=5)&&(++nCount<1000));
            if(nCount>=1000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            if(resSubNego1[0]!=0x05||resSubNego1[1]!=0x00){return NC_E_PROXY_PROTOCOL_VERSION_SUB|WSAGetLastError();};

            switch(resSubNego1[3])
            {
            case 0x01:
            {
            // IP V4
            char resSubNego2[6]={resSubNego1[4],0};
            int nRet=-1;
            if(FD_ISSET(m_socTCP,&fdread))
            {
            int nRcvd=0,nCount=0;
            do{
            int nRet = recv(m_socTCP,&resSubNego2[1]+nRcvd,5-nRcvd,0);
            if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            nRcvd += nRet;
            }
            while((nRcvd!=5)&&(++nCount<1000));
            if(nCount>=1000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            }
            // 得到代理綁定地址
            unsigned long ulBINDAddr = *(unsigned long*)&resSubNego2; // SOCKS BIND ADDR
            unsigned short usBINDPort = *(unsigned short*)&resSubNego2[4]; // SOCKS BIND PORT
            m_saiProxyBindTCP.sin_addr.S_un.S_addr=ulBINDAddr;
            m_saiProxyBindTCP.sin_port=usBINDPort;
            // 得到本機(jī)綁定地址
            int len = sizeof(m_saiHostTCP);
            getsockname(m_socTCP,(SOCKADDR*)&m_saiHostTCP,&len);
            }
            break;
            case 0x03:
            {
            // Domain name
            int nLen = resSubNego1[4]+2;
            char* presSubNego2 = new char[nLen];
            if(FD_ISSET(m_socTCP,&fdread))
            {
            int nRet=0,nRcvd=0,nCount=0;
            do{
            nRet = recv(m_socTCP,presSubNego2+nRcvd,nLen-nRcvd,0);
            if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            nRcvd += nRet;
            }
            while((nRcvd!=nLen)&&(++nCount<1000));
            if(nCount>=1000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            }
            unsigned short usBINDPort = *(unsigned short*)(presSubNego2+nLen-2); // BIND PORT;
            // 此時得到的是遠(yuǎn)程主機(jī)的Domain Name
            delete[] presSubNego2; presSubNego2=NULL;
            }
            break;
            case 0x04:
            {
            // IPV6
            AfxMessageBox("該版本不支持IPV6";
            }
            break;
            default:
            break;
            }

            // 至此,連接已經(jīng)建立。在此套接字上可進(jìn)行數(shù)據(jù)的收發(fā)。
            }

            2、UDP

            SOCKS V5提供了對UDP的支持,它通過在代理服務(wù)器和內(nèi)網(wǎng)主機(jī)之間建立一個UDP中繼的TCP連接,來輔助進(jìn)行UDP數(shù)據(jù)包的收發(fā)。此連接有一個有效期,在此有效生命周期內(nèi),必須往代理發(fā)送UDP數(shù)據(jù)報確認(rèn)連接有效,來維持此連接的有效性,否則,代理服務(wù)器超時,將會自動釋放此連接的資源。
            下面簡單地羅列程序?qū)崿F(xiàn),不涉及詳細(xì)的協(xié)議規(guī)范。

            // 客戶端為UDP中繼建立一個相關(guān)的流套接字
            SOCKET m_socClientTCP_UdpAssociate = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

            // 連接代理服務(wù)器
            int nRet=connect(m_socClientTCP_UdpAssociate,(SOCKADDR*)&saiProxy,sizeof(saiProxy));

            // 連接成功,開始和代理服務(wù)器協(xié)商,首先發(fā)送版本標(biāo)志,方法選擇報文
            const char reqNego[4]={(char)0x05,(char)0x02,(char)0x00,(char)0x02};
            nRet = send(m_socClientTCP_UdpAssociate,reqNego,4,0);
            if( nRet==SOCKET_ERROR
            {
            DWORD dwError = WSAGetLastError();
            if (dwError!=WSAEWOULDBLOCK) return NCM_E_WM_CREATE_PROXYREQUESTFAILED;
            }

            // 接收協(xié)商的響應(yīng)
            fd_set fdread; FD_ZERO(&fdread);
            FD_SET(m_socClientTCP_UdpAssociate,&fdread);
            if((nRet=select(0,&fdread,NULL,NULL,NULL))==SOCKET_ERROR) return NCM_E_WM_CREATE_PROXYCONNECTFAILED;
            char resNego[2]={0};
            int nRcvd=0,nCount=0;
            if(FD_ISSET(m_socClientTCP_UdpAssociate,&fdread))
            {
            nRcvd = recv(m_socClientTCP_UdpAssociate, (char*)resNego+nRcvd, 2,0);
            if(nRcvd==SOCKET_ERROR) return NCM_E_WM_CREATE_PROXYCONNECTFAILED;
            }
            if(resNego[0]!=0x05 || (resNego[1]!=0x00 && resNego[1]!=0x02)) return NCM_E_WM_CREATE_PROXYCONNECTFAILED;

            // 看是否需要密碼驗證
            if(resNego[1]==0x02)
            {
            // 需要密碼驗證
            char reqAuth[513]; memset(reqAuth,0,513);
            BYTE byLenUser = (BYTE)strlen(m_szProxyUserName);
            BYTE byLenPswd = (BYTE)strlen(m_szProxyPassword);
            reqAuth[0]=0x01;
            reqAuth[1]=byLenUser;
            sprintf(&reqAuth[2],"%s",m_szProxyUserName);
            reqAuth[2+byLenUser]=byLenPswd;
            sprintf(&reqAuth[3+byLenUser],"%s",m_szProxyPassword);
            //Send authentication info
            int len = (int)byLenUser + (int)byLenPswd + 3;
            int ret=send(m_socClientTCP_UdpAssociate,(const char*)reqAuth,len,0);
            if (ret==SOCKET_ERROR) if (GetLastError()!=WSAEWOULDBLOCK) return NCM_E_WM_CREATE_PROXYREQUESTFAILED;

            //Now : Response to the auth request
            char resAuth[2]={'\0'};
            int nRcvd=0,nCount=0;
            do{
            ret = recv(m_socClientTCP_UdpAssociate,resAuth+nRcvd,2-nRcvd,0);
            if(ret==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            nRcvd += nRet;
            }
            while((nRcvd!=2)&&(++nCount<1000));
            if(nCount>=1000){return NC_E_PROXY_RECEIVE}
            if (resAuth[1]!=0) return NEM_E_WM_CREATE_PROXYAUTHFAILED;
            // 密碼驗證通過了
            }

            // 開始發(fā)送向目標(biāo)服務(wù)器的連接請求,其中DST.ADDR是目標(biāo)服務(wù)器的地址,DST.PORT是目標(biāo)服務(wù)器的UDP端口
            char reqSubNego[10]={(char)0x05,(char)0x03,(char)0x00,(char)0x01,(char)0x00,(char)0x00,(char)0x00,(char)0x00,(char)0x00,(char)0x00};
            *(unsigned long*)&reqSubNego[4] =saiServerUDP.sin_addr.S_un.S_addr; // cmd: DEST.addr
            *(unsigned short*)&reqSubNego[8]=saiServerUDP.sin_port; // cmd: DEST.port in network octet order
            nRet=send(m_socClientTCP_UdpAssociate,(const char*)reqSubNego,10,0);
            if (nRet==SOCKET_ERROR) return NEM_E_WM_CREATE_PROXYREQFAILED;

            // 接收響應(yīng)信息
            int nRecvCount = 0;
            int nRecvBufferLen = 10;
            char szRecvBuf[10];
            nRet = 0;
            if(FD_ISSET(m_socClientTCP_UdpAssociate,&fdread))
            {
            int nRcvd=0,nCount=0;
            do{
            nRet = recv(m_socClientTCP_UdpAssociate,(char*)szRecvBuf+nRcvd,10-nRcvd,0);
            if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
            nRcvd += nRet;
            }
            while((nRcvd!=10)&&(++nCount<1000));
            if(nCount>=1000){return NC_E_PROXY_RECEIVE;}
            if (szRecvBuf[0]!=0x05||szRecvBuf[1]!=0x00){return NC_E_PROXY_PROTOCOL_VERSION_SUB;}
            }
            else
            {
            return NCM_E_WM_CREATE_PROXYREQUESTFAILED;
            }

            // 代理服務(wù)器綁定udp地址BND.ADR,一般代理服務(wù)器都是多宿主機(jī)器,因此這個綁定地址是局域網(wǎng)地址,代理服務(wù)器綁定udp端口BND.PORT
            // m_ulProxyUDPAddr 代理綁定地址
            // m_usUDPAssociatePort 代理綁定端口
            memmove(&m_ulProxyUDPAddr,&szRecvBuf[4],4);
            memmove(&m_usUDPAssociatePort,&szRecvBuf[8],2);

            m_bUDPAssociated = TRUE;
            // 至此,得到了代理綁定的地址和端口,客戶端就可以通過它來收發(fā)UDP數(shù)據(jù)報了


            // 客戶端收發(fā)實例
            // 首先創(chuàng)建數(shù)據(jù)報套接字,綁定套接字,得到本地數(shù)據(jù)報套接字地址,端口
            SOCKET m_socClientUDP=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
            SOCKADDR_IN saiLocal;
            memset(&saiLocal,0,sizeof(saiLocal));
            saiLocal.sin_family = AF_INET;
            saiLocal.sin_port = 0;
            saiLocal.sin_addr.S_un.S_addr = INADDR_ANY;
            // 綁定本地udp套接字地址,地址+端口由系統(tǒng)決定
            if (bind(m_socClientUDP, (SOCKADDR *)&saiLocal, sizeof(saiLocal) == SOCKET_ERROR)
            getsockname(m_socClientUDP, (sockaddr*)&saiLocal, &len);
            // m_ulHostAddr 本機(jī)綁定地址
            // m_usHostPortUdp 本機(jī)綁定端口
            m_ulHostAddr = saiLocal.sin_addr.S_un.S_addr;
            m_usHostPortUdp = saiLocal.sin_port;

            // 按照格式,發(fā)送數(shù)據(jù)
            SOCKADDR_IN saiProxy;
            memset(&saiProxy,0,sizeof(saiProxy));
            saiProxy.sin_family = AF_INET;
            saiProxy.sin_addr.S_un.S_addr = m_ulProxyUDPAddr; // 代理綁定的udp地址
            saiProxy.sin_port = m_usUDPAssociatePort; // 代理綁定的udp端口

            // 每個UDP包必須攜帶如下所述的頭:
            +----+------+------+----------+----------+----------+
            |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
            +----+------+------+----------+----------+----------+
            | 2 | 1 | 1 | Variable | 2 | Variable |
            +----+------+------+----------+----------+----------+
            // 其中 ATYP==0x01 表示采用 IPV4 地址,那么頭長度就是10,DST.ADDR并不是服務(wù)器地址,而是本機(jī)綁定地址,DST.PORT是本機(jī)綁定端口
            char buf[10+2]={'0x00','0x00','0x00','0x01','0xff'};
            memmove(&buf[4],&m_ulHostAddr,4);
            *(unsigned short*)&buf[8]=m_usHostPortUDP;
            int nRet = sendto(m_socClientUDP,buf,12,0,(SOCKADDR*)&saiProxy,sizeof(saiProxy));

            // 接收數(shù)據(jù)
            int nLen = sizeof(saiProxy);
            char buf=new char[MAX_UDPLEN];
            nRet = recvfrom(m_socClientUDP,buf,MAX_UDPLEN,0,(SOCKADDR *)&saiProxy,&nLen);
            if(nRet==SOCKET_ERROR) return SOCKET_ERROR;
            BYTE flag=0xff;
            if(memcmp(&buf[0],&flag,1)==0) return SOCKET_ERROR;
            BYTE byProxyHead[20];
            byProxyHead[0]=byProxyHead[1]=byProxyHead[2]=0;
            byProxyHead[3]=1;
            *(unsigned long*)&byProxyHead[4] = saiServerUDP.sin_addr.S_un.S_addr;
            *(unsigned short*)&byProxyHead[8] = saiServerUDP.sin_port;
            byProxyHead[10]=byProxyHead[11]=byProxyHead[12]=0;
            byProxyHead[13]=1;
            *(unsigned long*)&byProxyHead[14] = m_ulHostAddr;
            *(unsigned short*)&byProxyHead[18] = m_usHostPortUdp;

            int i=0;
            BOOL bIsForMe=FALSE;
            if(memcmp(&byProxyHead[0],&buf[i],4)==0)
            {
            unsigned long ulRetAddr = *(unsigned long*)&buf[i+4];
            if(ulRetAddr==m_ulHostAddr)
            {
            unsigned short usRetPort = ntohs((unsigned short)(*(unsigned short*)&buf[i+8]));
            if(usRetPort==m_usHostPortUdp)
            {
            bIsForMe=TRUE;
            }
            }
            i+=10;
            }
            // 客戶端收發(fā)結(jié)束


            // 服務(wù)器端發(fā)送實例
            // m_ulProxyUDPAddr 代理綁定地址
            // m_usUDPAssociatePort 代理綁定端口
            // m_ulHostAddr 本機(jī)綁定地址
            // m_usHostPortUdp 本機(jī)綁定端口
            // 客戶端必須把上面的m_ulProxyUDPAddr,m_usUDPAssociatePort,m_ulHostAddr,m_usHostPortUdp告知服務(wù)器,服務(wù)器通過這兩個套接字進(jìn)行數(shù)據(jù)的收發(fā)

            // 服務(wù)器創(chuàng)建數(shù)據(jù)報套接字
            SOCKET m_socUDP=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_OVERLAPPED);

            // 代理的udp中繼地址
            SOCKADDR_IN saiClient;
            saiClient.sin_family = AF_INET;
            saiClient.sin_addr.S_un.S_addr = m_ulProxyUDPAddr;
            saiClient.sin_port = m_usUDPAssociatePort;
            // 如果遠(yuǎn)程目標(biāo)在代理服務(wù)器后面,透過代理,指定遠(yuǎn)程目標(biāo)的socks信息,參照RFC1928
            char buffer[10]={'\0'};
            buffer[0]=buffer[1]=buffer[2]=0;
            buffer[3]=1; // No Fragment, It's a dependent udp, no need for socks server to arrange udp fragments

            // 目標(biāo)機(jī)器的地址端口,透過代理后發(fā)向這里
            *(int*)&buffer[4]=m_ulHostAddr;
            *(unsigned short*)&buffer[8]=m_usHostPortUdp;
            BYTE buf[DATA_BUFSIZE]={'\0'};
            memmove(&buf[10],&szSendbuf[0],dwLength);
            memmove(&buf[0],&buffer[0],10);
            int nSent = sendto(m_socUDP, (const char*)&buf[0], dwLength+10, 0, (SOCKADDR*)&saiClient,sizeof(saiClient));
            // 服務(wù)器端發(fā)送結(jié)束  回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2008-10-21 02:29 聶文龍
            關(guān)于通過http代理訪問Internet
            最近在網(wǎng)上查了一點關(guān)于通過Socket代理或者h(yuǎn)ttp代理訪問internet的資料,國內(nèi)的資料比較少,查到了一點英文資料,覺得講得還不錯。
            When an HTTP connection is made through a proxy server the client (usually the browser) sends the request to the proxy. The proxy opens the connection to the destination, sends the request, receives the response and sends it back to the client. The HTTP protocol specifies a request method called CONNECT. The CONNECT method can be used by the client to inform the proxy server that a connection to some host on some port is required. The proxy server, if allows such connections, tries to connect to the destination address specified in the request header. If it the operation fails it sends back to the client a negative HTTP response and close the connection. If the operation succeeded then send back an HTTP positive response and the connection is consider established. After that, the proxy does not care what data is transferred between client requesting the connection and the destination. It just forwards data in both ways acting as a tunnel.

            About the protocol
            We are interested in CONNECT method from the HTTP protocol. After the applications opens a connection with the proxy server it must send the connect request in the form of an HTTP request:

            CONNECT <destination_address>:<destination_port> <http_version><CR><LF><header_line><CR><LF><header_line><CR><LF>...<header_line><CR><LF><CR><LF>The proxy server process the request and try to make a connection to <destionation_address>:<destination_port>.

            The proxy server sends back an HTTP response in the form:

            <http_version> <code> <message><CR><LF><header_line><CR><LF><header_line><CR><LF>...<header_line><CR><LF><CR><LF>If it is a positive response (code=200) then after the empty line the proxy begins to acts as a tunnel and forwards data. If it is a negative response (code!=200) then connection is closed after the empty line.

            The HTTPTunneling application
            The application act as specified in a configuration file. An entry in the configuration file locks like this:

            <Source port> <Destination address> <Destination port> <Proxy address> <Proxy port>If the application is running and an entry in the configuration files changes, the application automatically updates itself.

            For every entry in the configuration file the application creates a port listener. This is a thread that opens a socket on <Source port> and waits for connection. When a request arrives on that port it tries to open a tunnel to the <Destination address>:< port>. If the <Proxy address> and <Proxy port> are missing, a direct connection is made. If the field are present it opens a connection to the proxy and sends a CONNECT request using the method specified above. The tunnel construction is made in a separate thread to let the port listener to accept immediatelly new connections. After the connection is established a tunnel object is constructed based on the opened sockets, sockets are marked as non-blocking and the object is passed to manager object. The thread that has created the tunnel is destroyed. Data transfer is made on a single thread. When one of the ends closes the connection the tunnel closes the other and the tunnel is marked as inactive. The manager finds the tunnel inactive and removes it from the list of active tunnels. By default the application generates log information in HTTPTunneling.log file. This file can be consulted to find wrong application behaviour.
              回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2008-10-21 11:35 聶文龍
            [轉(zhuǎn)載]C語言寫的Linux平臺socks5代理程序
            C語言寫的Linux平臺socks5代理程序

            信息來源:邪惡八進(jìn)制信息安全團(tuán)隊(www.eviloctal.com)

            前幾天MSN老上不去,我還以為是公司做了防火墻限制。于是把去年這個時候?qū)懙靡粋€代理程序改了改,拿出來用。結(jié)果發(fā)現(xiàn)MSN是因為微軟的問題,鄙視啊……
            因為寫得比較急,這個只支持TCP代理,UDP的我沒寫,因為MSN用不上。這個代碼可以隨意修改分發(fā),不過最好能給我一份。

            這是頭文件:
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Socks5代理頭文件,定義協(xié)議相關(guān)數(shù)據(jù)包結(jié)構(gòu)
            // 版本 0.1,作者 云舒
            // 2007年1月9日凌晨1點15分,GF回家已經(jīng)11天了。
            // 2008年1月25日修改,今年GF一直在我身邊,哈哈
            //
            // 參考:
            // http://www.rfc-editor.org/rfc/rfc1928.txt
            // http://www.rfc-editor.org/rfc/rfc1929.txt
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

            #ifndef SOCKS5_H
            #define SOCKS5_H

            #define VERSION 0x05
            #define CONNECT 0x01
            #define IPV4 0x01
            #define DOMAIN 0x03
            #define IPV6 0x04

            typedef struct _method_select_response // 協(xié)商方法服務(wù)器響應(yīng)
            {
            char version; // 服務(wù)器支持的Socks版本,0x04或者0x05
            char select_method;// 服務(wù)器選擇的方法,0x00為匿名,0x02為密碼認(rèn)證
            } METHOD_SELECT_RESPONSE;

            typedef struct _method_select_request // 協(xié)商方法服務(wù)端請求
            {
            char version; // 客戶端支持的版本,0x04或者0x05
            char number_methods; // 客戶端支持的方法的數(shù)量
            char methods[255]; // 客戶端支持的方法類型,最多255個,0x00為匿名,0x02為密碼認(rèn)證
            } METHOD_SELECT_REQUEST;

            typedef struct _AUTH_RESPONSE // 用戶密碼認(rèn)證服務(wù)端響應(yīng)
            {
            char version;// 版本,此處恒定為0x01
            char result;// 服務(wù)端認(rèn)證結(jié)果,0x00為成功,其他均為失敗
            } AUTH_RESPONSE;

            typedef struct _AUTH_REQUEST //用戶密碼認(rèn)證客戶端請求
            {
            char version; // 版本,此處恒定為0x01
            char name_len; // 第三個字段用戶名的長度,一個字節(jié),最長為0xff
            char name[255]; // 用戶名
            char pwd_len;// 第四個字段密碼的長度,一個字節(jié),最長為0xff
            char pwd[255]; // 密碼
            } AUTH_REQUEST;

            typedef struct _SOCKS5_RESPONSE // 連接真實主機(jī),Socks代理服務(wù)器響應(yīng)
            {
            char version; // 服務(wù)器支持的Socks版本,0x04或者0x05
            char reply; // 代理服務(wù)器連接真實主機(jī)的結(jié)果,0x00成功
            char reserved; // 保留位,恒定位0x00
            char address_type; // Socks代理服務(wù)器綁定的地址類型,IP V4為0x01,IP V6為0x04,域名為0x03
            char address_port[1]; // 如果address_type為域名,此處第一字節(jié)為域名長度,其后為域名本身,無0字符結(jié)尾,域名后為Socks代理服務(wù)器綁定端口
            }SOCKS5_RESPONSE;

            typedef struct _SOCKS5_REQUEST // 客戶端請求連接真實主機(jī)
            {
            char version; // 客戶端支持的Socks版本,0x04或者0x05
            char cmd; // 客戶端命令,CONNECT為0x01,BIND為0x02,UDP為0x03,一般為0x01
            char reserved; // 保留位,恒定位0x00
            char address_type; // 客戶端請求的真實主機(jī)的地址類型,IP V4為0x00,IP V6為0x04,域名為 0x03 char address_port[1]; // 如果address_type為域名,此處第一字節(jié)為域名長度,其后為域名本身,無0字符結(jié)尾,域名后為真實主機(jī)綁定端口

            }SOCKS5_REQUEST;
            #endif
            主程序來了:
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Socks5程序,只支持TCP代理
            // 版本 0.1,作者 云舒
            // 2007年1月9日凌晨1點15分,GF回家已經(jīng)11天了。
            // 2008年1月25日修改,今年GF一直在我身邊,哈哈
            //
            // 參考:
            // http://www.rfc-editor.org/rfc/rfc1928.txt
            // http://www.rfc-editor.org/rfc/rfc1929.txt
            //編譯:
            // gcc -o socks5 -O2 Socks5.c -lpthread( RedHat AS5測試 )
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

            #include <stdio.h>
            #include <netinet/in.h>
            #include <netdb.h>
            #include <sys/time.h>
            #include <sys/types.h>
            #include <unistd.h>
            #include <stdlib.h>
            #include <signal.h>
            #include <pthread.h>
            #include <errno.h>
            #include <string.h>
            #include <sys/socket.h>
            #include <arpa/inet.h>

            #include "Socks5.h"

            #define MAX_USER 10
            #define BUFF_SIZE 1024

            #define AUTH_CODE 0x02

            #define TIME_OUT 6000000

            #define USER_NAME "yunshu"
            #define PASS_WORD "ph4nt0m"

            // Select auth method, return 0 if success, -1 if failed
            int SelectMethod( int sock )
            {
            char recv_buffer[BUFF_SIZE] = { 0 };
            char reply_buffer[2] = { 0 };

            METHOD_SELECT_REQUEST *method_request;
            METHOD_SELECT_RESPONSE *method_response;

            // recv METHOD_SELECT_REQUEST
            int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
            if( ret <= 0 )
            {
            perror( "recv error" );
            close( sock );

            return -1;
            }

            //printf( "SelectMethod: recv %d bytes\n", ret );

            // if client request a wrong version or a wrong number_method
            method_request = (METHOD_SELECT_REQUEST *)recv_buffer;
            method_response = (METHOD_SELECT_RESPONSE *)reply_buffer;

            method_response->version = VERSION;

            // if not socks5
            if( (int)method_request->version != VERSION )
            {
            method_response->select_method = 0xff;

            send( sock, method_response, sizeof(METHOD_SELECT_RESPONSE), 0 );
            close( sock );

            return -1;
            }

            method_response->select_method = AUTH_CODE;
            if( -1 == send( sock, method_response, sizeof(METHOD_SELECT_RESPONSE), 0 ) )
            {
            close( sock );
            return -1;
            }

            return 0;
            }

            // test password, return 0 for success.
            int AuthPassword( int sock )
            {
            char recv_buffer[BUFF_SIZE] = { 0 };
            char reply_buffer[BUFF_SIZE] = { 0 };

            AUTH_REQUEST *auth_request;
            AUTH_RESPONSE *auth_response;

            // auth username and password
            int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
            if( ret <= 0 )
            {
            perror( "recv username and password error" );
            close( sock );
            return -1;
            }
            //printf( "AuthPass: recv %d bytes\n", ret );

            auth_request = (AUTH_REQUEST *)recv_buffer;

            memset( reply_buffer, 0, BUFF_SIZE );
            auth_response = (AUTH_RESPONSE *)reply_buffer;
            auth_response->version = 0x01;

            char recv_name[256] = { 0 };
            char recv_pass[256] = { 0 };

            // auth_request->name_len is a char, max number is 0xff
            char pwd_str[2] = { 0 };
            strncpy( pwd_str, auth_request->name + auth_request->name_len, 1 );
            int pwd_len = (int)pwd_str[0];

            strncpy( recv_name, auth_request->name, auth_request->name_len );
            strncpy( recv_pass, auth_request->name + auth_request->name_len + sizeof(auth_request->pwd_len), pwd_len );

            //printf( "username: %s\npassword: %s\n", recv_name, recv_pass );
            // check username and password
            if( (strncmp( recv_name, USER_NAME, strlen(USER_NAME) ) == 0) &&
            (strncmp( recv_pass, PASS_WORD, strlen(PASS_WORD) ) == 0)
            )
            {
            auth_response->result = 0x00;
            if( -1 == send( sock, auth_response, sizeof(AUTH_RESPONSE), 0 ) )
            {
            close( sock );
            return -1;
            }
            else
            {
            return 0;
            }
            }
            else
            {
            auth_response->result = 0x01;
            send( sock, auth_response, sizeof(AUTH_RESPONSE), 0 );

            close( sock );
            return -1;
            }
            }

            // parse command, and try to connect real server.
            // return socket for success, -1 for failed.
            int ParseCommand( int sock )
            {
            char recv_buffer[BUFF_SIZE] = { 0 };
            char reply_buffer[BUFF_SIZE] = { 0 };

            SOCKS5_REQUEST *socks5_request;
            SOCKS5_RESPONSE *socks5_response;

            // recv command
            int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
            if( ret <= 0 )
            {
            perror( "recv connect command error" );

            close( sock );
            return -1;
            }

            socks5_request = (SOCKS5_REQUEST *)recv_buffer;
            if( (socks5_request->version != VERSION) || (socks5_request->cmd != CONNECT) ||
            (socks5_request->address_type == IPV6) )
            {
            //printf( "connect command error.\n" );
            close( sock );
            return -1;
            }

            // begain process connect request
            struct sockaddr_in sin;

            memset( (void *)&sin, 0, sizeof(struct sockaddr_in) );
            sin.sin_family = AF_INET;

            // get real server&#39;s ip address
            if( socks5_request->address_type == IPV4 )
            {
            memcpy( &sin.sin_addr.s_addr, &socks5_request->address_type + sizeof(socks5_request->address_type) , 4 );
            memcpy( &sin.sin_port, &socks5_request->address_type + sizeof(socks5_request->address_type) + 4, 2 );

            //printf( "Real Server: %s %d\n", inet_ntoa( sin.sin_addr ), ntohs( sin.sin_port ) );
            }
            else if( socks5_request->address_type == DOMAIN )
            {
            char domain_length = *(&socks5_request->address_type + sizeof(socks5_request->address_type));
            char target_domain[ 256] = { 0 };

            strncpy( target_domain, &socks5_request->address_type + 2, (unsigned int)domain_length );

            //printf( "target: %s\n", target_domain );

            struct hostent *phost = gethostbyname( target_domain );
            if( phost == NULL )
            {
            //printf( "Resolve %s error!\n" , target_domain );

            close( sock );
            return -1;
            }
            memcpy( &sin.sin_addr , phost->h_addr_list[0] , phost->h_length );

            memcpy( &sin.sin_port, &socks5_request->address_type + sizeof(socks5_request->address_type) +
            sizeof(domain_length) + domain_length, 2 );
            }

            // try to connect to real server
            int real_server_sock = socket( AF_INET, SOCK_STREAM, 0 );
            if( real_server_sock < 0 )
            {
            perror( "Socket creation failed\n");

            close( sock );
            return -1;
            }

            memset( reply_buffer, 0, sizeof(BUFF_SIZE) );

            socks5_response = (SOCKS5_RESPONSE *)reply_buffer;

            socks5_response->version = VERSION;
            socks5_response->reserved = 0x00;
            socks5_response->address_type = 0x01;
            memset( socks5_response + 4, 0 , 6 );

            ret = connect( real_server_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) );
            if( ret == 0 )
            {
            socks5_response->reply = 0x00;
            if( -1 == send( sock, socks5_response, 10, 0 ) )
            {
            close( sock );

            return -1;
            }
            }
            else
            {
            perror( "Connect to real server error" );
            socks5_response->reply = 0x01;
            send( sock, socks5_response, 10, 0 );

            close( sock );
            return -1;
            }

            return real_server_sock;
            }

            int ForwardData( int sock, int real_server_sock )
            {
            char recv_buffer[BUFF_SIZE] = { 0 };

            fd_set fd_read;
            struct timeval time_out;

            time_out.tv_sec = 0;
            time_out.tv_usec = TIME_OUT;

            int ret = 0;

            while( 1 )
            {
            FD_ZERO( &fd_read );
            FD_SET( sock, &fd_read );
            FD_SET( real_server_sock, &fd_read );

            ret = select( (sock > real_server_sock ? sock : real_server_sock) + 1, &fd_read, NULL, NULL, &time_out );
            if( -1 == ret )
            {
            perror( "select socket error" );
            break;
            }
            else if( 0 == ret )
            {
            //perror( "select time out" );
            continue;
            }

            //printf( "[DEBUG] testing readable!\n" );
            if( FD_ISSET(sock, &fd_read) )
            {
            //printf( "client can read!\n" );
            memset( recv_buffer, 0, BUFF_SIZE );
            ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
            if( ret > 0 )
            {
            //printf( "%s", recv_buffer );
            //printf( "recv %d bytes from client.\n", ret );
            ret = send( real_server_sock, recv_buffer, ret, 0 );
            if( ret == -1 )
            {
            perror( "send data to real server error" );
            break;
            }
            //printf( "send %d bytes to client!\n", ret );
            }
            else if( ret == 0 )
            {
            //printf( "client close socket.\n" );
            break;
            }
            else
            {
            //perror( "recv from client error" );
            break;
            }
            }

            else if( FD_ISSET(real_server_sock, &fd_read) )
            {
            //printf( "real server can read!\n" );
            memset( recv_buffer, 0, BUFF_SIZE );
            ret = recv( real_server_sock, recv_buffer, BUFF_SIZE, 0 );
            if( ret > 0 )
            {
            //printf( "%s", recv_buffer );
            //printf( "recv %d bytes from real server.\n", ret );
            ret = send( sock, recv_buffer, ret, 0 );
            if( ret == -1 )
            {
            perror( "send data to client error" );
            break;
            }
            }
            else if( ret == 0 )
            {
            //printf( "real server close socket.\n" );
            break;
            }
            else
            {
            perror( "recv from real server error" );
            break;
            }
            }
            }

            return 0;
            }

            int Socks5( void *client_sock )
            {
            int sock = *(int *)client_sock;

            if( SelectMethod( sock ) == -1 )
            {
            //printf( "socks version error\n" );
            return -1;
            }

            if( AuthPassword( sock ) == -1 )
            {
            //printf( "auth password error\n" );
            return -1;
            }

            int real_server_sock = ParseCommand( sock );
            if( real_server_sock == -1 )
            {
            //printf( "parse command error.\n" );
            return -1;
            }

            ForwardData( sock, real_server_sock );

            close( sock );
            close( real_server_sock );

            return 0;
            }

            int main( int argc, char *argv[] )
            {
            if( argc != 2 )
            {
            printf( "Socks5 proxy for test,code by YunShu\n" );
            printf( "Usage: %s <proxy_port>\n", argv[0] );
            printf( "Options:\n" );
            printf( " <proxy_port> ---which port of this proxy server will listen.\n" );

            return 1;
            }

            struct sockaddr_in sin;

            memset( (void *)&sin, 0, sizeof( struct sockaddr_in) );
            sin.sin_family = AF_INET;
            sin.sin_port = htons( atoi(argv[1]) );
            sin.sin_addr.s_addr = htonl(INADDR_ANY);

            int listen_sock = socket( AF_INET, SOCK_STREAM, 0 );
            if( listen_sock < 0 )
            {
            perror( "Socket creation failed\n");
            return -1;
            }

            int opt = SO_REUSEADDR;
            setsockopt( listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) );

            if( bind( listen_sock, (struct sockaddr*)&sin, sizeof(struct sockaddr_in) ) < 0 )
            {
            perror( "Bind error" );
            return -1;
            }

            if( listen( listen_sock, MAX_USER ) < 0 )
            {
            perror( "Listen error" );
            return -1;
            }

            struct sockaddr_in cin;
            int client_sock;
            int client_len = sizeof( struct sockaddr_in );

            while( client_sock = accept( listen_sock, (struct sockaddr *)&cin, (socklen_t *)&client_len ) )
            {
            printf( "Connected from %s, processing......\n", inet_ntoa( cin.sin_addr ) );

            pthread_t work_thread;
            if( pthread_create( &work_thread, NULL, (void *)Socks5, (void *)&client_sock ) )
            {
            perror( "Create thread error..." );
            close( client_sock );
            }
            else
            {
            pthread_detach( work_thread );
            }
            }
            }   回復(fù)  更多評論
              
            # re: 代理服務(wù)器代碼 2012-05-08 23:16 迷失
            聊天記錄  回復(fù)  更多評論
              

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            久久综合久久综合亚洲| 伊人久久大香线蕉综合Av| 国产A三级久久精品| 91性高湖久久久久| 亚洲精品蜜桃久久久久久| 久久成人精品| 中文字幕精品久久久久人妻| 久久婷婷五月综合色高清| 欧美久久亚洲精品| 国产激情久久久久影院老熟女| 久久亚洲AV无码精品色午夜 | 欧美va久久久噜噜噜久久| 久久se这里只有精品| 久久99精品综合国产首页| 久久国产精品99久久久久久老狼| 久久综合色老色| 久久国产视屏| 日韩精品久久久久久| av无码久久久久久不卡网站 | 麻豆成人久久精品二区三区免费 | 久久九九久精品国产| 国产一久久香蕉国产线看观看| 亚洲伊人久久大香线蕉综合图片 | 色综合久久天天综合| 久久精品午夜一区二区福利| 精品国产日韩久久亚洲| 色婷婷久久综合中文久久一本 | 99久久成人18免费网站| 国产美女久久精品香蕉69| 久久精品国产精品亚洲毛片 | 亚洲欧美伊人久久综合一区二区| 久久精品成人免费国产片小草| 品成人欧美大片久久国产欧美| 99久久婷婷免费国产综合精品| 色综合久久中文字幕无码| 色偷偷偷久久伊人大杳蕉| 亚洲午夜无码久久久久| 久久久久久久久无码精品亚洲日韩| 久久亚洲精品成人无码网站| 亚洲人成网亚洲欧洲无码久久 | 99久久精品免费看国产|