socket穿透代理代码(C++版)

写代码经常会遇到socket要通过代理连接服务器的情况,代理类型通畅有三种:HTTP、SOCK4和SOCK5,通过学习和网上参考相关代码,写了个代理类来实现该功能,贴出来与大家共享


才贴出来两天,刚在百度一搜竟然发现已被一字不改的转载到好几个网站去了,连转载的字样都没有,不反对转载分享,可能否注明出处?


头文件

[cpp]  view plain copy
  1. #pragma once  
  2.   
  3. #include <WinSock2.h>  
  4. #include <string>  
  5. #include <vector>  
  6.   
  7. using namespace std;  
  8.   
  9. enum ProxyStatus  
  10. {  
  11.     SUCCESS,  
  12.     CONNECT_PROXY_FAIL,  
  13.     NOT_CONNECT_PROXY,  
  14.     CONNECT_SERVER_FAIL  
  15. };  
  16.   
  17. class CProxy  
  18. {  
  19. public:  
  20.     CProxy(long type, string ip, u_short port, string username, string password)  
  21.         :m_proxyType(type), m_proxyIp(ip), m_proxyPort(port), m_proxyUserName(username), m_proxyUserPwd(password)  
  22.     {}  
  23.   
  24.     ~CProxy(void){};  
  25.   
  26.     ProxyStatus ConnectProxyServer(SOCKET socket);  
  27.     ProxyStatus ConnectServer(SOCKET socket, string ip, u_short port);  
  28.   
  29. private:  
  30.     ProxyStatus ConnectByHttp(SOCKET socket, string ip, u_short port);  
  31.     ProxyStatus ConnectBySock4(SOCKET socket, string ip, u_short port);  
  32.     ProxyStatus ConnectBySock5(SOCKET socket, string ip, u_short port);  
  33.   
  34.     bool Send(SOCKET socket, const char* buf, int len);  
  35.     int Receive(SOCKET socket, char* buf, int bufLen);  
  36.   
  37. private:  
  38.     long m_proxyType;  
  39.     string m_proxyIp;  
  40.     u_short m_proxyPort;  
  41.     string m_proxyUserName;  
  42.     string m_proxyUserPwd;  
  43.   
  44.     bool m_blnProxyServerOk;  
  45. };  
  46.   
  47. struct TSock4req1   
  48. {   
  49.     char VN;   
  50.     char CD;   
  51.     unsigned short Port;   
  52.     unsigned long IPAddr;   
  53.     char other;   
  54. };   
  55.   
  56. struct TSock4ans1   
  57. {   
  58.     char VN;   
  59.     char CD;   
  60. };  
  61.   
  62. struct TSock5req1   
  63. {   
  64.     char Ver;   
  65.     char nMethods;   
  66.     char Methods;   
  67. };   
  68.   
  69. struct TSock5ans1   
  70. {   
  71.     char Ver;   
  72.     char Method;   
  73. };   
  74.   
  75. struct TSock5req2   
  76. {   
  77.     char Ver;   
  78.     char Cmd;   
  79.     char Rsv;   
  80.     char Atyp;   
  81.     char other;   
  82. };   
  83.   
  84. struct TSock5ans2   
  85. {   
  86.     char Ver;   
  87.     char Rep;   
  88.     char Rsv;   
  89.     char Atyp;   
  90.     char other;   
  91. };   
  92.   
  93. struct TAuthreq   
  94. {   
  95.     char Ver;   
  96.     char Ulen;   
  97.     char Name;   
  98.     char PLen;   
  99.     char Pass;   
  100. };   
  101.   
  102. struct TAuthans   
  103. {   
  104.     char Ver;   
  105.     char Status;   
  106. };   

实现文件

[cpp]  view plain copy
  1. #include "StdAfx.h"  
  2. #include "Proxy.h"  
  3. #include "Base64.h"  
  4. #include "log.h"  
  5.   
  6. #include <time.h>  
  7.   
  8.   
  9. ProxyStatus CProxy::ConnectProxyServer(SOCKET socket)  
  10. {  
  11.     int ret;  
  12.     struct timeval timeout ;  
  13.     fd_set r;  
  14.     string ip;  
  15.     u_short port;  
  16.   
  17.     ip = m_proxyIp;  
  18.     port = m_proxyPort;  
  19.   
  20.     sockaddr_in servAddr;  
  21.     servAddr.sin_family = AF_INET;  
  22.     servAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());  
  23.     servAddr.sin_port = htons(port);  
  24.   
  25.     //设置非阻塞方式连接  
  26.     unsigned long ul = 1;  
  27.     ret = ioctlsocket(socket, FIONBIO, (unsigned long*)&ul);  
  28.     if(ret == SOCKET_ERROR)   
  29.     {  
  30.         return CONNECT_PROXY_FAIL;  
  31.     }  
  32.   
  33.     connect(socket, (sockaddr*)&servAddr, sizeof(sockaddr));  
  34.   
  35.     FD_ZERO(&r);  
  36.     FD_SET(socket, &r);  
  37.     timeout.tv_sec = 5;   
  38.     timeout.tv_usec =0;  
  39.     ret = select(0, 0, &r, 0, &timeout);  
  40.   
  41.     if (ret <= 0)  
  42.     {  
  43.         m_blnProxyServerOk = false;  
  44.         return CONNECT_PROXY_FAIL;  
  45.     }  
  46.     else  
  47.     {  
  48.         m_blnProxyServerOk = true;  
  49.         return SUCCESS;  
  50.     }  
  51. }  
  52.   
  53. ProxyStatus CProxy::ConnectServer(SOCKET socket, string ip, u_short port)  
  54. {  
  55.     int ret;  
  56.     int nTimeout;  
  57.   
  58.     if (!m_blnProxyServerOk)  
  59.     {  
  60.         return NOT_CONNECT_PROXY;  
  61.     }  
  62.   
  63.     nTimeout = 5000;  
  64.     setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(int));    //设置接收超时  
  65.   
  66.     unsigned long ul = 0;  
  67.     ret = ioctlsocket(socket, FIONBIO, (unsigned long*)&ul);    //设置阻塞方式连接  
  68.   
  69.     switch(m_proxyType)  
  70.     {  
  71.     case 0: //HTTP  
  72.         return ConnectByHttp(socket, ip, port);  
  73.         break;  
  74.     case 1: //SOCK4  
  75.         return ConnectBySock4(socket, ip, port);  
  76.         break;  
  77.     case 2: //SOCK5  
  78.         return ConnectBySock5(socket, ip, port);  
  79.         break;  
  80.     default:  
  81.         break;  
  82.     }  
  83.   
  84.     return CONNECT_SERVER_FAIL;  
  85. }  
  86.   
  87. ProxyStatus CProxy::ConnectByHttp(SOCKET socket, string ip, u_short port)  
  88. {  
  89.     char buf[512];  
  90.   
  91.     if (m_proxyUserName != "")  
  92.     {  
  93.         string str;  
  94.         string strBase64;  
  95.         str = m_proxyUserName + ":" + m_proxyUserPwd;  
  96.         strBase64 = CBase64::Encode((unsigned char*)str.c_str(), str.length());  
  97.         sprintf_s(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\nAuthorization: Basic %s\r\n\r\nProxy-Authorization: Basic %s\r\n\r\n",   
  98.             ip.c_str(), port, ip.c_str(), port, strBase64.c_str(), strBase64.c_str());  
  99.     }  
  100.     else  
  101.     {  
  102.         //sprintf_s(buf, 512, "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n\r\n", ip.c_str(), port, ip.c_str(), port);  
  103.         sprintf_s(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\nUser-Agent: MyApp/0.1\r\n\r\n", ip.c_str(), port);  
  104.     }  
  105.   
  106.     Send(socket, buf, strlen(buf));  
  107.     Receive(socket, buf, sizeof(buf));  
  108.   
  109.     if (strstr(buf, "HTTP/1.0 200 Connection established") != NULL)  
  110.     {  
  111.         return SUCCESS;  
  112.     }  
  113.     else  
  114.     {  
  115.         return CONNECT_SERVER_FAIL;  
  116.     }  
  117.   
  118. }  
  119.   
  120. ProxyStatus CProxy::ConnectBySock4(SOCKET socket, string ip, u_short port)  
  121. {  
  122.     char buf[512];  
  123.   
  124.     memset(buf, 0, sizeof(buf));   
  125.     struct TSock4req1 *proxyreq;  
  126.     proxyreq = (struct TSock4req1*)buf;   
  127.     proxyreq->VN = 4;   
  128.     proxyreq->CD = 1;   
  129.     proxyreq->Port = ntohs(port);   
  130.     proxyreq->IPAddr = inet_addr(ip.c_str());   
  131.   
  132.     Send(socket, buf, 9);  
  133.   
  134.     struct TSock4ans1 *proxyans;   
  135.     proxyans = (struct TSock4ans1*)buf;   
  136.     memset(buf, 0, sizeof(buf));   
  137.   
  138.     Receive(socket, buf, sizeof(buf));  
  139.     if(proxyans->VN == 0 && proxyans->CD == 90)   
  140.     {   
  141.         return SUCCESS;   
  142.     }   
  143.     else  
  144.     {  
  145.         return CONNECT_SERVER_FAIL;  
  146.     }  
  147. }  
  148.   
  149. ProxyStatus CProxy::ConnectBySock5(SOCKET socket, string ip, u_short port)  
  150. {  
  151.     char buf[512];  
  152.   
  153.     struct TSock5req1 *proxyreq1;   
  154.     proxyreq1 = (struct TSock5req1 *)buf;   
  155.     proxyreq1->Ver = 5;   
  156.     proxyreq1->nMethods = 1;   
  157.     proxyreq1->Methods = m_proxyUserName != "" ? 2 : 0;  
  158.   
  159.     Send(socket, buf, 3);   
  160.       
  161.     struct TSock5ans1 *proxyans1;   
  162.     proxyans1 = (struct TSock5ans1 *)buf;   
  163.   
  164.     memset(buf, 0, sizeof(buf));  
  165.     Receive(socket, buf, sizeof(buf));  
  166.     if(proxyans1->Ver != 5 || (proxyans1->Method != 0 && proxyans1->Method != 2))   
  167.     {   
  168.         return CONNECT_SERVER_FAIL;   
  169.     }  
  170.   
  171.     if(proxyans1->Method == 2)   
  172.     {   
  173.         int nUserLen = m_proxyUserName.length();  
  174.         int nPassLen = m_proxyUserPwd.length();  
  175.         //struct TAuthreq *authreq;   
  176.         //authreq = (struct TAuthreq *)buf;   
  177.         //authreq->Ver = 1;   
  178.         //authreq->Ulen = nUserLen;   
  179.         //strcpy(authreq->Name, m_proxyUserName.c_str());   
  180.         //authreq->PLen = nPassLen;   
  181.         //strcpy(authreq->Pass, m_proxyUserPwd.c_str());   
  182.   
  183.         buf[0] = 1;  
  184.         buf[1] = nUserLen;  
  185.         memcpy(buf + 2, m_proxyUserName.c_str(), nUserLen);  
  186.         buf[2 + nUserLen] = nPassLen;  
  187.         memcpy(buf + 3 + nUserLen, m_proxyUserPwd.c_str(), nPassLen);  
  188.   
  189.         Send(socket, buf, 3 + nUserLen + nPassLen);  
  190.   
  191.         struct TAuthans *authans;   
  192.         authans = (struct TAuthans *)buf;   
  193.         memset(buf, 0, sizeof(buf));   
  194.   
  195.         Receive(socket, buf, sizeof(buf));  
  196.         if(authans->Ver != 1 || authans->Status != 0)   
  197.         {   
  198.             return CONNECT_SERVER_FAIL;  
  199.         }   
  200.     }  
  201.   
  202.     memset(buf, 0, sizeof(buf));  
  203.     struct TSock5req2 *proxyreq2;   
  204.     proxyreq2 = (struct TSock5req2 *)buf;   
  205.     proxyreq2->Ver = 5;   
  206.     proxyreq2->Cmd = 1;   
  207.     proxyreq2->Rsv = 0;   
  208.     proxyreq2->Atyp = 1;   
  209.     unsigned long tmpLong = inet_addr(ip.c_str());   
  210.     unsigned short port1 = ntohs(port);   
  211.     memcpy((char*)&proxyreq2->other, &tmpLong, 4);   
  212.     memcpy((char*)(&proxyreq2->other) + 4, &port1, 2);   
  213.   
  214.     //Send(socket, buf, sizeof(struct TSock5req2) + 5);   
  215.     Send(socket, buf, 10);   
  216.     struct TSock5ans2 *proxyans2;   
  217.     memset(buf ,0, sizeof(buf));   
  218.     proxyans2 = (struct TSock5ans2 *)buf;   
  219.       
  220.     Receive(socket, buf, sizeof(buf));  
  221.     if(proxyans2->Ver != 5 || proxyans2->Rep != 0)   
  222.     {   
  223.         return CONNECT_SERVER_FAIL;   
  224.     }  
  225.   
  226.     return SUCCESS;  
  227. }  
  228.   
  229. int CProxy::Receive(SOCKET socket, char* buf, int bufLen)  
  230. {  
  231.     return recv(socket, buf, bufLen, 0);  
  232. }  
  233.   
  234. bool CProxy::Send(SOCKET socket, const char* buf, int len)  
  235. {  
  236.     long ilen = len;  
  237.     int sendCnt = 0;  
  238.     int ret;  
  239.   
  240.     while(sendCnt < ilen)  
  241.     {  
  242.         if((ret = send(socket, buf + sendCnt, ilen - sendCnt, 0)) == SOCKET_ERROR)  
  243.         {  
  244.             return false;  
  245.         }  
  246.         else  
  247.         {  
  248.             sendCnt += ret;  
  249.         }  
  250.     }  
  251.   
  252.     return true;  
  253. }  

proxy中用到的CBase64类

头文件

[cpp]  view plain copy
  1. #pragma once  
  2.   
  3. #include <string>  
  4.   
  5. using namespace std;  
  6.   
  7. class CBase64  
  8. {  
  9. private:  
  10.     CBase64(void);  
  11. public:  
  12.     ~CBase64(void);  
  13.   
  14.     static string Encode(const unsigned char* Data,int DataByte);  
  15.     static string Decode(const char* Data,int DataByte,int& OutByte);  
  16. };  

实现文件

[cpp]  view plain copy
  1. #include "StdAfx.h"  
  2. #include "Base64.h"  
  3.   
  4. CBase64::CBase64(void)  
  5. {  
  6. }  
  7.   
  8. CBase64::~CBase64(void)  
  9. {  
  10. }  
  11.   
  12. string CBase64::Encode(const unsigned char* Data,int DataByte)  
  13. {  
  14.     //编码表  
  15.     const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
  16.     //返回值  
  17.     string strEncode;  
  18.     unsigned char Tmp[4]={0};  
  19.     int LineLength=0;  
  20.     for(int i=0;i<(int)(DataByte / 3);i++)  
  21.     {  
  22.         Tmp[1] = *Data++;  
  23.         Tmp[2] = *Data++;  
  24.         Tmp[3] = *Data++;  
  25.         strEncode+= EncodeTable[Tmp[1] >> 2];  
  26.         strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];  
  27.         strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];  
  28.         strEncode+= EncodeTable[Tmp[3] & 0x3F];  
  29.         if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}  
  30.     }  
  31.     //对剩余数据进行编码  
  32.     int Mod=DataByte % 3;  
  33.     if(Mod==1)  
  34.     {  
  35.         Tmp[1] = *Data++;  
  36.         strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];  
  37.         strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];  
  38.         strEncode+= "==";  
  39.     }  
  40.     else if(Mod==2)  
  41.     {  
  42.         Tmp[1] = *Data++;  
  43.         Tmp[2] = *Data++;  
  44.         strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];  
  45.         strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];  
  46.         strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];  
  47.         strEncode+= "=";  
  48.     }  
  49.   
  50.     return strEncode;  
  51. }  
  52.   
  53. string CBase64::Decode(const char* Data,int DataByte,int& OutByte)  
  54. {  
  55.     //解码表  
  56.     const char DecodeTable[] =  
  57.     {  
  58.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
  59.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
  60.         62, // '+'  
  61.         0, 0, 0,  
  62.         63, // '/'  
  63.         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'  
  64.         0, 0, 0, 0, 0, 0, 0,  
  65.         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,  
  66.         13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'  
  67.         0, 0, 0, 0, 0, 0,  
  68.         26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,  
  69.         39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'  
  70.     };  
  71.     //返回值  
  72.     string strDecode;  
  73.     int nValue;  
  74.     int i= 0;  
  75.     while (i < DataByte)  
  76.     {  
  77.         if (*Data != '\r' && *Data!='\n')  
  78.         {  
  79.             nValue = DecodeTable[*Data++] << 18;  
  80.             nValue += DecodeTable[*Data++] << 12;  
  81.             strDecode+=(nValue & 0x00FF0000) >> 16;  
  82.             OutByte++;  
  83.             if (*Data != '=')  
  84.             {  
  85.                 nValue += DecodeTable[*Data++] << 6;  
  86.                 strDecode+=(nValue & 0x0000FF00) >> 8;  
  87.                 OutByte++;  
  88.                 if (*Data != '=')  
  89.                 {  
  90.                     nValue += DecodeTable[*Data++];  
  91.                     strDecode+=nValue & 0x000000FF;  
  92.                     OutByte++;  
  93.                 }  
  94.             }  
  95.             i += 4;  
  96.         }  
  97.         else// 回车换行,跳过  
  98.         {  
  99.             Data++;  
  100.             i++;  
  101.         }  
  102.     }  
  103.     return strDecode;  
  104. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值