青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 298  文章 - 377  trackbacks - 0
<2016年9月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

常用鏈接

留言簿(34)

隨筆分類

隨筆檔案

文章檔案

相冊(cè)

收藏夾

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

/*************************************  
    *   一個(gè)基礎(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;  
          //   上級(jí)代理服務(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)建一個(gè)代理線程。  
          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   {  
                                  //   獲取請(qǐng)求行的內(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;   //   跳過(guò)多個(gè)空白字符  
                      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);  
                                                          //   分析可能存在的端口號(hào)  
          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或其派生類的實(shí)例  
  }   catch   (Exception   e)   {    
          Socket   esock   =   (Socket)arg[0];  
          try   {   esock.close();   }   catch   (Exception   ec)   {}  
  }  
          }  
  }   catch   (IOException   e)   {  
  }  
          }  
   
   
          //   測(cè)試用的簡(jiǎn)單main方法  
          static   public   void   main(String   args[])   {  
  System.out.println("在端口808啟動(dòng)代理服務(wù)器\n");  
  HttpProxy.log=System.out;  
  HttpProxy.logging=false;  
  HttpProxy.startProxy(808,HttpProxy.class);  
              }  
          }  
  //   HttpProxy的簡(jiǎn)單派生類  
  //   不記錄主機(jī)名字  
  //   在日志輸出的每一行前面加上一個(gè)'*'  
   
  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;  
          }  
          //   測(cè)試用的簡(jiǎn)單main方法  
          static   public   void   main(String   args[])   {  
  System.out.println("在端口808啟動(dòng)代理服務(wù)器\n");  
  HttpProxy.log=System.out;  
  HttpProxy.logging=true;  
  HttpProxy.startProxy(808,SubHttpProxy.class);  
              }  
   
   
  }  
posted on 2008-10-21 02:02 聶文龍 閱讀(7140) 評(píng)論(11)  編輯 收藏 引用

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

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

你的目的是要和服務(wù)器做UDP的數(shù)據(jù)傳送。
步驟:
1,和代理建立tcp聯(lián)接,(你已經(jīng)完成)
2,向代理發(fā)送版本的請(qǐng)求信息,
我的實(shí)現(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)返回成功,是嗎?
如果失敗,斷開(kāi)建立的tcp聯(lián)接,
如果成功,如果需要用戶驗(yàn)證則進(jìn)行步驟3,否則進(jìn)行4,
3,如果需要用戶驗(yàn)證,則
類似:
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 );
}
如果失敗,斷開(kāi)建立的tcp聯(lián)接,
如果用戶返回成功,步驟4
4,發(fā)送請(qǐng)求的協(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()來(lái)邦定一個(gè)端口。
char temp;
temp = tempbuf[8] ;
tempbuf[8] = tempbuf[9];
tempbuf[9] = temp;

int senddatalen = send(m_sock, (char *)tempbuf, datasize, 0 );
}
如果失敗,斷開(kāi)建立的tcp聯(lián)接,
如果返回成功,驗(yàn)證完畢!步驟5
5,真正的數(shù)據(jù)傳送,用代理傳送的時(shí)候,數(shù)據(jù)包的前面加上10個(gè)字節(jié)
類似:
void CCommunicator::CopyDataHead(BYTE * ptempbuf)
{
struct in_addr addr;
addr.s_addr = inet_addr(“202.220.33.333”);//這個(gè)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ā)到那個(gè)服務(wù)器的端口,也就是你的qq服務(wù)器。
char temp;
temp = ptempbuf[8] ;
ptempbuf[8] = ptempbuf[9];
ptempbuf[9] = temp;
}
真正發(fā)送的時(shí)候類似:
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ā)送請(qǐng)求的時(shí)候返回的代理服務(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);

}
希望對(duì)你有幫助!  回復(fù)  更多評(píng)論
  
# 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ì)過(guò)程中,我們經(jīng)常要與各種類型的代理服務(wù)器打交道,比如在企業(yè)內(nèi)部網(wǎng)通過(guò)代理去訪問(wèn)Internet網(wǎng)上的服務(wù)器等等,一般代理服務(wù)器支持幾種常見(jiàn)的代理協(xié)議標(biāo)準(zhǔn),如Socks4,Socks5,Http代理,其中Socks5需要用戶驗(yàn)證,代理相對(duì)復(fù)雜。我在查閱RFC文檔和相關(guān)資料后,特總結(jié)一些TCP協(xié)議穿透代理服務(wù)器的程序片斷,希望對(duì)大家有所幫助。

//使用到的結(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;
};

//通過(guò)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("通過(guò)代理連接主站不成功!");
 ClientSock.Close();
 return FALSE;
}




//通過(guò)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("通過(guò)代理連接主站不成功!");
 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ù)器用戶驗(yàn)證不成功!");
  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("通過(guò)代理連接主站不成功!");
 ClientSock.Close();
 return FALSE;
}




//通過(guò)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ā)送請(qǐng)求
memset(buff,0,600);
ClientSock.Receive(buff,600);
if(strstr(buff, "HTTP/1.0 200 Connection established") == NULL) //連接不成功
{
 m_sError = _T("通過(guò)代理連接主站不成功!");
 ClientSock.Close();
 return FALSE;
}


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

<正文完>   回復(fù)  更多評(píng)論
  
# 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("通過(guò)代理連接主站不成功!");
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("通過(guò)代理連接主站不成功!");
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ù)器用戶驗(yàn)證不成功!");
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("通過(guò)代理連接主站不成功!");
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ā)送請(qǐng)求
memset(buff,0,600);
ClientSock.Receive(buff,600);
if(strstr(buff, "HTTP/1.0 200 Connection established") == NULL) //連接不成功
{
m_sError = _T("通過(guò)代理連接主站不成功!");
ClientSock.Close();
return ;
}


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

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

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的請(qǐng)求和返回
發(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ù)  更多評(píng)論
  
# re: 代理服務(wù)器代碼 2008-10-21 02:12 聶文龍
簡(jiǎn)單代理服務(wù)器C代碼實(shí)現(xiàn)(SOLARIS)

/*
** 編寫(xiě):無(wú)可非議
** 來(lái)源:WWW.20CN.NET
** 注意:請(qǐng)注明轉(zhuǎn)貼來(lái)源
*/

#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; //偵聽(tīng)套接字
char m_ConnectAddr[256] = {0}; //目標(biāo)地址
char m_ConnectPort[256] = {0}; //目標(biāo)端口

/*
** 函數(shù)名稱: GetListenSocket
** 函數(shù)功能: 生成偵聽(tīng)套接字
** 傳入?yún)?shù): Port : 偵聽(tīng)端口
** 傳出參數(shù): 無(wú)
** 引用函數(shù): 無(wú)
** 返回值 : 偵聽(tīng)套接字,為0時(shí)表示生成套接字失敗,其他為套接字句柄
** 備注 : 無(wú)
*/
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;
}

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

//偵聽(tīng)套接字生成成功
return m_Socket;
}

/*
** 函數(shù)名稱: GetConnectSocket
** 函數(shù)功能: 生成連接套接字
** 傳入?yún)?shù): pServerAddr : 連接地址 pServerPort : 連接端口
** 傳出參數(shù): 無(wú)
** 引用函數(shù): 無(wú)
** 返回值 : 連接套接字,為0時(shí)表示生成套接字失敗,其他為套接字句柄
** 備注 : 無(wú)
*/
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ì)算機(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ù): 無(wú)
** 引用函數(shù): 無(wú)
** 返回值 : 無(wú)
** 備注 : 逆反完成全雙工
*/
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))
{
//出錯(cuò)
break;
}
if(!FD_ISSET(m_RecvSocket,&readset)) continue;

ret = recv(m_RecvSocket,m_Buf,512 * 1024 - 1,0);
if(ret < 0)
{
//出錯(cuò)
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)程啟動(dòng)
** 傳入?yún)?shù): m_SendSocket : 發(fā)送套接字 m_RecvSocket : 接收套接字
** 傳出參數(shù): 無(wú)
** 引用函數(shù): 無(wú)
** 返回值 : 無(wú)
** 備注 : 逆反完成全雙工
*/
void SocketTrans()
{
struct sockaddr_in m_WorkAddr = {0};
int m_191Socket = 0;
int m_147socket = 0;
int m_WorkAddrLen = 0;

//開(kāi)始任務(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("致命錯(cuò)誤,無(wú)法建立新進(jìn)程!\n");
fflush(stdout);
close(m_191Socket);
close(m_147socket);
break;
}
else if(ret == 0)
{
//關(guān)閉原來(lái)端口
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)程信號(hào)處理函數(shù)
** 傳入?yún)?shù): 無(wú)
** 傳出參數(shù): 無(wú)
** 引用函數(shù): 無(wú)
** 返回值 : 無(wú)
** 備注 : 處理進(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ù): 無(wú)
** 傳出參數(shù): 無(wú)
** 引用函數(shù): MakeFilePath,GetMyInitInfo,SocketTrans
** 返回值 : 無(wú)
** 備注 : 為客戶接收進(jìn)程主函數(shù)
*/
int main(int argc,char* argv[])
{
//檢查參數(shù)合法性
if(argc != 4)
{
printf("格式:本地端口 目的地址 目的端口\n");
fflush(stdout);
return 0;
}

daemon_init();

//登記信號(hào)事件
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]);

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

m_MainId = getpid();
//啟動(dòng)文件接收偵聽(tīng)線程
SocketTrans();
close(m_ListenSocket);
return 0;
}
  回復(fù)  更多評(píng)論
  
# 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; // 用來(lái)聯(lián)結(jié)遠(yuǎn)程主機(jī)的端口
}; //這個(gè)結(jié)構(gòu)用來(lái)PROXY SERVER與遠(yuǎn)程主機(jī)的信息交換.


SOCKET gListen_Socket; //用來(lái)偵聽(tīng)的SOCKET。


int StartServer() //啟動(dòng)服務(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); //啟動(dòng)偵聽(tīng)
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); //啟動(dòng)另一偵聽(tīng).
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); /* 打開(kāi)一個(gè) 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))
{
// 錯(cuò)誤處理
cerr < < _T("Fatal Error: MFC initialization failed") < < endl;
nRetCode = 1;

}
else
{
// 主程序開(kāi)始.
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))
{
// 錯(cuò)誤處理
cerr < < _T("Fatal Error: MFC initialization failed") < < endl;
nRetCode = 1;
}
else
{
// 主程序開(kāi)始.
StartServer();
while(1)
if(getchar()=='q') break;
CloseServer();
}


return nRetCode;
}
  回復(fù)  更多評(píng)論
  
# 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){ //針對(duì)客戶端的接收處理線程
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){ //針對(duì)遠(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){ //針對(duì)一次服務(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)聽(tīng)線程
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選項(xiàng)中添加wsock32.lib和ws2_32.lib,或在文件前部加上如下語(yǔ)句:
#paragma comment(lib,"wsock32.lib")
#paragma comment(lib,"ws2_32.lib")

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


  回復(fù)  更多評(píng)論
  
# re: 代理服務(wù)器代碼 2008-10-21 02:23 聶文龍
VC++6實(shí)現(xiàn)簡(jiǎ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; // 用來(lái)聯(lián)結(jié)遠(yuǎn)程主機(jī)的端口
}; //這個(gè)結(jié)構(gòu)用來(lái)PROXY SERVER與遠(yuǎn)程主機(jī)的信息交換.

SOCKET gListen_Socket; //用來(lái)偵聽(tīng)的SOCKET。

int StartServer() //啟動(dòng)服務(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); //啟動(dòng)偵聽(tīng)
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); //啟動(dòng)另一偵聽(tīng).
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); /* 打開(kāi)一個(gè) 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))
{
// 錯(cuò)誤處理
cerr < < _T("Fatal Error: MFC initialization failed") < < endl;
nRetCode = 1;
}
else
{
// 主程序開(kāi)始.
StartServer();
while(1)
if(getchar()=='q') break;
CloseServer();
}

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

Socks5版本的協(xié)議說(shuō)明參考 RFC1928,RFC1929
下面簡(jiǎn)單地羅列程序?qū)崿F(xiàn),不涉及詳細(xì)的協(xié)議規(guī)范。首先對(duì)于TCP連接,然后再討論UDP傳輸。至于通過(guò)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ù)器成功后,馬上開(kāi)始和代理協(xié)商,協(xié)商報(bào)文如下,詢問(wèn)服務(wù)器,版本5,是需要驗(yàn)證(0x02)還是不需要驗(yàn)證(0x00)
  +------+-------------------+------------+
  |VER | Number of METHODS | METHODS |
  +------+-------------------+------------+
  | 0x05 | 0x02 (有兩個(gè)方法) | 0x00 | 0x02|
  +------+-------------------+------------+
const char reqNego[4]={(char)0x05,(char)0x02,(char)0x00,(char)0x02};
nRet = send(m_socTCP,reqNego,4,0);

// Setp 2: 代理服務(wù)器將返回兩個(gè)字節(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ā)送來(lái)的數(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é)果判斷是否需要驗(yàn)證用戶,如果是0x02,則需要提供驗(yàn)證,驗(yàn)證部分參考RFC1929
if(resNego[1]==0x02)
{
// 需要密碼驗(yàn)證
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;
// 密碼驗(yàn)證通過(guò)了
}

// Step 4: 協(xié)商完成,開(kāi)始發(fā)送連接遠(yuǎn)程服務(wù)器請(qǐng)求,請(qǐng)求報(bào)文格式如下:
  +----+-----+-------+------+----------+----------+
  |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ù)器端口
// 如果需要接受外來(lái)連接,則需要在連接完成之后,發(fā)送CMD==0x02綁定請(qǐng)求,代理將為此請(qǐng)求綁定一個(gè)套接字接受外部連接
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: 接收對(duì)請(qǐng)求的響應(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是這個(gè)套接字的端口
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;
// 此時(shí)得到的是遠(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提供了對(duì)UDP的支持,它通過(guò)在代理服務(wù)器和內(nèi)網(wǎng)主機(jī)之間建立一個(gè)UDP中繼的TCP連接,來(lái)輔助進(jìn)行UDP數(shù)據(jù)包的收發(fā)。此連接有一個(gè)有效期,在此有效生命周期內(nèi),必須往代理發(fā)送UDP數(shù)據(jù)報(bào)確認(rèn)連接有效,來(lái)維持此連接的有效性,否則,代理服務(wù)器超時(shí),將會(huì)自動(dòng)釋放此連接的資源。
下面簡(jiǎn)單地羅列程序?qū)崿F(xiàn),不涉及詳細(xì)的協(xié)議規(guī)范。

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

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

// 連接成功,開(kāi)始和代理服務(wù)器協(xié)商,首先發(fā)送版本標(biāo)志,方法選擇報(bà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;

// 看是否需要密碼驗(yàn)證
if(resNego[1]==0x02)
{
// 需要密碼驗(yàn)證
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;
// 密碼驗(yàn)證通過(guò)了
}

// 開(kāi)始發(fā)送向目標(biāo)服務(wù)器的連接請(qǐng)求,其中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ī)器,因此這個(gè)綁定地址是局域網(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;
// 至此,得到了代理綁定的地址和端口,客戶端就可以通過(guò)它來(lái)收發(fā)UDP數(shù)據(jù)報(bào)了


// 客戶端收發(fā)實(shí)例
// 首先創(chuàng)建數(shù)據(jù)報(bào)套接字,綁定套接字,得到本地?cái)?shù)據(jù)報(bào)套接字地址,端口
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端口

// 每個(gè)UDP包必須攜帶如下所述的頭:
+----+------+------+----------+----------+----------+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
+----+------+------+----------+----------+----------+
// 其中 ATYP==0x01 表示采用 IPV4 地址,那么頭長(zhǎng)度就是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ā)送實(shí)例
// m_ulProxyUDPAddr 代理綁定地址
// m_usUDPAssociatePort 代理綁定端口
// m_ulHostAddr 本機(jī)綁定地址
// m_usHostPortUdp 本機(jī)綁定端口
// 客戶端必須把上面的m_ulProxyUDPAddr,m_usUDPAssociatePort,m_ulHostAddr,m_usHostPortUdp告知服務(wù)器,服務(wù)器通過(guò)這兩個(gè)套接字進(jìn)行數(shù)據(jù)的收發(fā)

// 服務(wù)器創(chuàng)建數(shù)據(jù)報(bào)套接字
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ù)器后面,透過(guò)代理,指定遠(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ī)器的地址端口,透過(guò)代理后發(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ù)  更多評(píng)論
  
# re: 代理服務(wù)器代碼 2008-10-21 02:29 聶文龍
關(guān)于通過(guò)http代理訪問(wèn)Internet
最近在網(wǎng)上查了一點(diǎn)關(guān)于通過(guò)Socket代理或者h(yuǎn)ttp代理訪問(wèn)internet的資料,國(guó)內(nèi)的資料比較少,查到了一點(diǎn)英文資料,覺(jué)得講得還不錯(cuò)。
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ù)  更多評(píng)論
  
# re: 代理服務(wù)器代碼 2008-10-21 11:35 聶文龍
[轉(zhuǎn)載]C語(yǔ)言寫(xiě)的Linux平臺(tái)socks5代理程序
C語(yǔ)言寫(xiě)的Linux平臺(tái)socks5代理程序

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

前幾天MSN老上不去,我還以為是公司做了防火墻限制。于是把去年這個(gè)時(shí)候?qū)懙靡粋€(gè)代理程序改了改,拿出來(lái)用。結(jié)果發(fā)現(xiàn)MSN是因?yàn)槲④浀膯?wèn)題,鄙視啊……
因?yàn)閷?xiě)得比較急,這個(gè)只支持TCP代理,UDP的我沒(méi)寫(xiě),因?yàn)镸SN用不上。這個(gè)代碼可以隨意修改分發(fā),不過(guò)最好能給我一份。

這是頭文件:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Socks5代理頭文件,定義協(xié)議相關(guān)數(shù)據(jù)包結(jié)構(gòu)
// 版本 0.1,作者 云舒
// 2007年1月9日凌晨1點(diǎn)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ù)端請(qǐng)求
{
char version; // 客戶端支持的版本,0x04或者0x05
char number_methods; // 客戶端支持的方法的數(shù)量
char methods[255]; // 客戶端支持的方法類型,最多255個(gè),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)證客戶端請(qǐng)求
{
char version; // 版本,此處恒定為0x01
char name_len; // 第三個(gè)字段用戶名的長(zhǎng)度,一個(gè)字節(jié),最長(zhǎng)為0xff
char name[255]; // 用戶名
char pwd_len;// 第四個(gè)字段密碼的長(zhǎng)度,一個(gè)字節(jié),最長(zhǎng)為0xff
char pwd[255]; // 密碼
} AUTH_REQUEST;

typedef struct _SOCKS5_RESPONSE // 連接真實(shí)主機(jī),Socks代理服務(wù)器響應(yīng)
{
char version; // 服務(wù)器支持的Socks版本,0x04或者0x05
char reply; // 代理服務(wù)器連接真實(shí)主機(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é)為域名長(zhǎng)度,其后為域名本身,無(wú)0字符結(jié)尾,域名后為Socks代理服務(wù)器綁定端口
}SOCKS5_RESPONSE;

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

}SOCKS5_REQUEST;
#endif
主程序來(lái)了:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Socks5程序,只支持TCP代理
// 版本 0.1,作者 云舒
// 2007年1月9日凌晨1點(diǎn)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測(cè)試 )
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#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ù)  更多評(píng)論
  
# re: 代理服務(wù)器代碼 2012-05-08 23:16 迷失
聊天記錄  回復(fù)  更多評(píng)論
  

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


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
              欧美亚洲一区二区在线观看| 韩日在线一区| 亚洲欧美美女| 亚洲女女女同性video| 99精品免费视频| 91久久久久久| 欧美激情一区二区在线 | 亚洲精品视频中文字幕| 亚洲精品国产精品乱码不99 | 亚洲精品在线看| 亚洲图中文字幕| 久久蜜桃香蕉精品一区二区三区| 欧美高清在线视频| 国产精品视频福利| 亚洲第一精品夜夜躁人人爽| 亚洲精品小视频在线观看| 亚洲影院高清在线| 久久久久欧美精品| 99国产精品视频免费观看| 欧美亚洲日本国产| 欧美精品 日韩| 久久在线免费观看| 亚洲精品欧美专区| 性做久久久久久免费观看欧美| 久久尤物视频| 亚洲精品一区中文| 久久精品国产免费观看| 欧美日韩大片| 激情一区二区三区| 亚洲一区制服诱惑| 欧美国产亚洲精品久久久8v| 亚洲一品av免费观看| 免费永久网站黄欧美| 国产美女一区二区| 日韩视频二区| 久久综合久久88| 亚洲一区观看| 欧美日本高清| 91久久精品国产91久久| 久久久久久久久久久一区| 正在播放日韩| 欧美日韩一区综合| 亚洲精品中文在线| 欧美成人精品在线观看| 欧美一区二区三区四区高清| 国产精品护士白丝一区av| 亚洲人妖在线| 蜜桃久久精品乱码一区二区| 欧美伊人久久久久久久久影院| 国产精品久久久久9999吃药| 亚洲视频自拍偷拍| 一本色道久久综合狠狠躁篇的优点 | 亚洲综合色婷婷| 欧美日韩福利视频| 亚洲精品一区在线| 欧美黄色成人网| 看片网站欧美日韩| 在线观看国产日韩| 免费毛片一区二区三区久久久| 欧美亚洲一区二区在线| 国产精品亚洲一区二区三区在线| 亚洲在线免费视频| 亚洲视频在线看| 国产精品久久久久久影视| 在线一区亚洲| 亚洲色图制服丝袜| 国产精品入口尤物| 欧美一区二粉嫩精品国产一线天| 中文国产成人精品久久一| 国产精品v片在线观看不卡| 亚洲女同性videos| 小嫩嫩精品导航| 国产一区二区三区在线观看精品 | 校园激情久久| 久久久久久久久久码影片| 国产一区欧美日韩| 蜜臀99久久精品久久久久久软件 | 国产综合香蕉五月婷在线| 久久精品国产v日韩v亚洲| 欧美一级网站| 国产精品一区二区三区四区五区| 欧美中在线观看| 久久这里只有| 国产精品99久久久久久久久| 亚洲一区二区三区777| 国产日韩一区二区三区| 猛干欧美女孩| 欧美日韩在线播放一区二区| 久久精品国产成人| 蜜臀久久99精品久久久久久9| 亚洲伦伦在线| 亚洲欧美综合精品久久成人 | 欧美三级小说| 久久久久国色av免费看影院| 欧美成人免费全部| 亚洲一区在线观看视频| 亚洲综合99| 亚洲国产高清在线| 中文在线资源观看网站视频免费不卡 | 中文在线一区| 黑人一区二区| 亚洲人成人99网站| 国产视频精品xxxx| 亚洲精品美女久久久久| 国产精品羞羞答答xxdd| 亚洲二区免费| 国产日韩欧美综合| 亚洲精品麻豆| 亚洲高清中文字幕| 性欧美精品高清| 国产精品99久久久久久人| 欧美在线视频导航| 亚洲欧美日韩国产成人精品影院 | 欧美日韩黄色一区二区| 久久久之久亚州精品露出| 欧美激情第10页| 久久久噜久噜久久综合| 欧美视频网站| 亚洲区中文字幕| 亚洲二区视频在线| 午夜一区在线| 一区二区三区精品视频| 久久视频一区| 久久久噜噜噜久久中文字幕色伊伊 | 欧美日韩国产黄| 蜜桃av一区二区三区| 亚洲国产精品久久91精品| 欧美日韩和欧美的一区二区| 看片网站欧美日韩| 国产日韩欧美一区| 亚洲一区免费视频| 亚洲一区二区精品| 欧美日韩一区二区三区免费看| 欧美激情一区二区三区蜜桃视频 | 欧美一区二区精美| 亚洲综合国产| 国产精品国产三级国产专区53| 亚洲精选久久| 一本色道久久综合狠狠躁的推荐| 免费成年人欧美视频| 欧美高清免费| 亚洲国产一区二区三区在线播 | 亚洲激情视频| 亚洲美女少妇无套啪啪呻吟| 欧美国产精品日韩| 亚洲激情电影中文字幕| 9色精品在线| 免费观看久久久4p| 亚洲电影视频在线| 男人的天堂成人在线| 久热爱精品视频线路一| 在线成人亚洲| 欧美国产日韩精品| 亚洲人成在线免费观看| 一区二区三欧美| 国产精品v欧美精品∨日韩| 午夜精品久久久久久久蜜桃app| 久久久九九九九| 亚洲黄页一区| 国产精品盗摄久久久| 亚洲欧美成人网| 老司机精品久久| 99国产精品久久久久久久| 国产精品成人久久久久| 久久riav二区三区| 亚洲国内自拍| 欧美一级在线亚洲天堂| 永久免费视频成人| 99精品欧美一区二区蜜桃免费| 翔田千里一区二区| 伊人成人在线| 欧美视频在线免费| 久久黄色网页| 夜夜爽99久久国产综合精品女不卡 | 亚洲激情视频| 国产精品久久久999| 久久久久久香蕉网| 亚洲精品一区中文| 麻豆国产精品va在线观看不卡 | 久久亚洲午夜电影| 亚洲精品一区二区三区樱花| 国产精品午夜在线观看| 樱桃国产成人精品视频| 亚洲一区日本| 欧美激情视频一区二区三区在线播放 | 国产专区一区| 欧美日韩国产小视频在线观看| 亚洲欧美电影在线观看| 欧美xx69| 久久久一区二区三区| 日韩视频免费观看高清完整版| 欧美午夜激情小视频| 久久精品91久久香蕉加勒比| 亚洲片国产一区一级在线观看| 久久激情视频免费观看| 宅男精品视频| 亚洲欧洲日产国码二区| 国产在线乱码一区二区三区| 欧美日韩精品伦理作品在线免费观看 | 1000部国产精品成人观看|