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

隨筆 - 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>
              亚洲一区二区三区中文字幕| 久久精品欧美| 欧美日韩在线三区| 一区二区三区 在线观看视| 亚洲一区二区视频在线观看| 久久亚洲二区| 99在线精品观看| 麻豆精品精华液| 亚洲一区二区视频在线观看| 亚洲免费福利视频| 国产情侣一区| 欧美精品18+| 久久久999国产| 日韩一级不卡| 黄色在线一区| 欧美性jizz18性欧美| 久久久久免费视频| 亚洲一区二区黄| 欧美在线免费视屏| 亚洲天堂视频在线观看| 国产欧美韩日| 国产伦精品一区| 久久精品一区蜜桃臀影院 | 亚洲国产一区二区视频| 欧美国产精品专区| 午夜日韩激情| 在线一区二区日韩| 99精品视频免费| 欧美一区综合| 亚洲男同1069视频| 一区二区精品在线| 亚洲清纯自拍| 在线国产亚洲欧美| 激情视频一区二区| 亚洲欧洲日本mm| 欧美在线看片a免费观看| 午夜精品视频| 欧美在线中文字幕| 亚洲精品国久久99热| 亚洲高清自拍| 亚洲国产一区二区三区高清 | 99在线|亚洲一区二区| 亚洲三级免费观看| 亚洲夫妻自拍| 在线观看免费视频综合| 国产一区视频观看| 国产在线精品成人一区二区三区| 亚洲精品久久久久久久久久久久久| 亚洲在线免费观看| 欧美日韩一二三四五区| 亚洲精品日韩久久| 亚洲激情电影在线| 最新国产成人在线观看| 亚洲在线中文字幕| 欧美主播一区二区三区美女 久久精品人| 欧美亚洲专区| 裸体女人亚洲精品一区| 亚洲无吗在线| 欧美色网在线| 亚洲线精品一区二区三区八戒| 欧美激情视频网站| 日韩视频在线观看国产| 亚洲永久在线| 国产精品嫩草久久久久| 黄色成人在线观看| 日韩午夜一区| 亚洲欧洲在线播放| 欧美成人日本| 国产精品区二区三区日本| 原创国产精品91| 久久国产精品久久久| 看欧美日韩国产| 欧美一区二区三区四区在线观看地址| 久久色中文字幕| 在线观看一区二区视频| 老司机精品视频网站| 久久影院午夜论| 国产精品久久久久久久午夜片| 亚洲香蕉伊综合在人在线视看| 亚洲毛片在线看| 欧美亚男人的天堂| 欧美中文字幕在线观看| 亚洲电影观看| 欧美日韩国产一级片| 国产综合第一页| 麻豆精品国产91久久久久久| 欧美成人国产一区二区| 亚洲一区成人| 欧美在线首页| 亚洲久久在线| 亚洲欧美乱综合| 亚洲第一精品福利| 亚洲精品综合| 精品成人在线观看| 亚洲美女黄色| 红桃视频成人| 日韩亚洲在线| 激情小说另类小说亚洲欧美 | 99视频精品免费观看| 国产精品毛片| 欧美激情一区二区| 国产精品区一区二区三区| 美女主播一区| 欧美一区二区啪啪| 亚洲伦理在线| 久久av红桃一区二区小说| 亚洲人成在线影院| 午夜精品久久久久久久久久久久 | 国产日韩欧美综合精品| 亚洲国产精品久久| 免费不卡欧美自拍视频| 欧美视频官网| 久久理论片午夜琪琪电影网| 亚洲午夜精品久久久久久app| 国产视频观看一区| 亚洲国产精品综合| 国产亚洲一区二区精品| 午夜精品福利一区二区蜜股av| 久久精品国产69国产精品亚洲| 国产欧美69| 亚洲二区视频在线| 国产午夜精品久久| 中国成人黄色视屏| 亚洲精品乱码| 久久美女性网| 久久精品国亚洲| 欧美日韩一区二区免费视频| 欧美电影在线观看完整版| 久久久亚洲国产天美传媒修理工| 99在线精品视频| 麻豆精品在线播放| 老司机精品视频网站| 国产一区二区三区视频在线观看| 一区二区高清视频| 在线亚洲精品| 欧美乱大交xxxxx| 99re成人精品视频| 欧美91大片| 欧美在线观看一区二区| 国产精品多人| 欧美二区在线看| 在线免费观看成人网| 久久成人免费| 久久精品色图| 在线播放日韩欧美| 欧美激情bt| 中日韩美女免费视频网址在线观看| 亚洲一区国产一区| 国产区精品视频| 久久久久久噜噜噜久久久精品 | 欧美日韩一卡| 亚洲丝袜av一区| 久久久精品久久久久| 亚洲第一区色| 欧美二区在线| 一区二区三区欧美激情| 欧美在线不卡| 在线成人激情视频| 欧美日韩国产系列| 性高湖久久久久久久久| 国内一区二区在线视频观看| 久久久噜噜噜久噜久久| 亚洲日本一区二区| 亚洲已满18点击进入久久| 国产乱码精品一区二区三区五月婷 | 久久久久久久91| 欧美国产日本在线| 一本色道88久久加勒比精品| 国产精品成av人在线视午夜片| 午夜天堂精品久久久久| 欧美大片在线观看一区| 在线一区二区三区做爰视频网站 | 亚洲一区在线观看视频| 亚洲一区二区三区高清| 国产午夜精品久久久久久久| 久久久www成人免费无遮挡大片 | 一本久久综合| 亚洲一级一区| 国产原创一区二区| 欧美精品一区二区三区在线看午夜| 亚洲高清久久网| 欧美一进一出视频| 在线视频精品一区| 一区二区电影免费观看| 国产精品高清在线| 久久久九九九九| 亚洲一区欧美激情| 亚洲精品综合精品自拍| 久久青青草综合| 国产亚洲va综合人人澡精品| 欧美高清一区二区| 亚洲午夜极品| 亚洲美女视频在线观看| 欧美一级播放| 99精品福利视频| 亚洲国产婷婷香蕉久久久久久| 91久久久在线| 麻豆成人在线| 一本久久综合亚洲鲁鲁| 亚洲韩国一区二区三区|