写代码经常会遇到socket要通过代理连接服务器的情况,代理类型通畅有三种:HTTP、SOCK4和SOCK5,通过学习和网上参考相关代码,写了个代理类来实现该功能,贴出来与大家共享
才贴出来两天,刚在百度一搜竟然发现已被一字不改的转载到好几个网站去了,连转载的字样都没有,不反对转载分享,可能否注明出处?
头文件
- #pragma once
- #include <WinSock2.h>
- #include <string>
- #include <vector>
- using namespace std;
- enum ProxyStatus
- {
- SUCCESS,
- CONNECT_PROXY_FAIL,
- NOT_CONNECT_PROXY,
- CONNECT_SERVER_FAIL
- };
- class CProxy
- {
- public:
- CProxy(long type, string ip, u_short port, string username, string password)
- :m_proxyType(type), m_proxyIp(ip), m_proxyPort(port), m_proxyUserName(username), m_proxyUserPwd(password)
- {}
- ~CProxy(void){};
- ProxyStatus ConnectProxyServer(SOCKET socket);
- ProxyStatus ConnectServer(SOCKET socket, string ip, u_short port);
- private:
- ProxyStatus ConnectByHttp(SOCKET socket, string ip, u_short port);
- ProxyStatus ConnectBySock4(SOCKET socket, string ip, u_short port);
- ProxyStatus ConnectBySock5(SOCKET socket, string ip, u_short port);
- bool Send(SOCKET socket, const char* buf, int len);
- int Receive(SOCKET socket, char* buf, int bufLen);
- private:
- long m_proxyType;
- string m_proxyIp;
- u_short m_proxyPort;
- string m_proxyUserName;
- string m_proxyUserPwd;
- bool m_blnProxyServerOk;
- };
- struct TSock4req1
- {
- char VN;
- char CD;
- unsigned short Port;
- unsigned long IPAddr;
- char other;
- };
- struct TSock4ans1
- {
- char VN;
- char CD;
- };
- struct TSock5req1
- {
- char Ver;
- char nMethods;
- char Methods;
- };
- struct TSock5ans1
- {
- char Ver;
- char Method;
- };
- struct TSock5req2
- {
- char Ver;
- char Cmd;
- char Rsv;
- char Atyp;
- char other;
- };
- struct TSock5ans2
- {
- char Ver;
- char Rep;
- char Rsv;
- char Atyp;
- char other;
- };
- struct TAuthreq
- {
- char Ver;
- char Ulen;
- char Name;
- char PLen;
- char Pass;
- };
- struct TAuthans
- {
- char Ver;
- char Status;
- };
实现文件
- #include "StdAfx.h"
- #include "Proxy.h"
- #include "Base64.h"
- #include "log.h"
- #include <time.h>
- ProxyStatus CProxy::ConnectProxyServer(SOCKET socket)
- {
- int ret;
- struct timeval timeout ;
- fd_set r;
- string ip;
- u_short port;
- ip = m_proxyIp;
- port = m_proxyPort;
- sockaddr_in servAddr;
- servAddr.sin_family = AF_INET;
- servAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
- servAddr.sin_port = htons(port);
- //设置非阻塞方式连接
- unsigned long ul = 1;
- ret = ioctlsocket(socket, FIONBIO, (unsigned long*)&ul);
- if(ret == SOCKET_ERROR)
- {
- return CONNECT_PROXY_FAIL;
- }
- connect(socket, (sockaddr*)&servAddr, sizeof(sockaddr));
- FD_ZERO(&r);
- FD_SET(socket, &r);
- timeout.tv_sec = 5;
- timeout.tv_usec =0;
- ret = select(0, 0, &r, 0, &timeout);
- if (ret <= 0)
- {
- m_blnProxyServerOk = false;
- return CONNECT_PROXY_FAIL;
- }
- else
- {
- m_blnProxyServerOk = true;
- return SUCCESS;
- }
- }
- ProxyStatus CProxy::ConnectServer(SOCKET socket, string ip, u_short port)
- {
- int ret;
- int nTimeout;
- if (!m_blnProxyServerOk)
- {
- return NOT_CONNECT_PROXY;
- }
- nTimeout = 5000;
- setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(int)); //设置接收超时
- unsigned long ul = 0;
- ret = ioctlsocket(socket, FIONBIO, (unsigned long*)&ul); //设置阻塞方式连接
- switch(m_proxyType)
- {
- case 0: //HTTP
- return ConnectByHttp(socket, ip, port);
- break;
- case 1: //SOCK4
- return ConnectBySock4(socket, ip, port);
- break;
- case 2: //SOCK5
- return ConnectBySock5(socket, ip, port);
- break;
- default:
- break;
- }
- return CONNECT_SERVER_FAIL;
- }
- ProxyStatus CProxy::ConnectByHttp(SOCKET socket, string ip, u_short port)
- {
- char buf[512];
- if (m_proxyUserName != "")
- {
- string str;
- string strBase64;
- str = m_proxyUserName + ":" + m_proxyUserPwd;
- strBase64 = CBase64::Encode((unsigned char*)str.c_str(), str.length());
- sprintf_s(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1 Host: %s:%d Authorization: Basic %s Proxy-Authorization: Basic %s ",
- ip.c_str(), port, ip.c_str(), port, strBase64.c_str(), strBase64.c_str());
- }
- else
- {
- //sprintf_s(buf, 512, "CONNECT %s:%d HTTP/1.1 Host: %s:%d ", ip.c_str(), port, ip.c_str(), port);
- sprintf_s(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1 User-Agent: MyApp/0.1 ", ip.c_str(), port);
- }
- Send(socket, buf, strlen(buf));
- Receive(socket, buf, sizeof(buf));
- if (strstr(buf, "HTTP/1.0 200 Connection established") != NULL)
- {
- return SUCCESS;
- }
- else
- {
- return CONNECT_SERVER_FAIL;
- }
- }
- ProxyStatus CProxy::ConnectBySock4(SOCKET socket, string ip, u_short port)
- {
- char buf[512];
- memset(buf, 0, sizeof(buf));
- struct TSock4req1 *proxyreq;
- proxyreq = (struct TSock4req1*)buf;
- proxyreq->VN = 4;
- proxyreq->CD = 1;
- proxyreq->Port = ntohs(port);
- proxyreq->IPAddr = inet_addr(ip.c_str());
- Send(socket, buf, 9);
- struct TSock4ans1 *proxyans;
- proxyans = (struct TSock4ans1*)buf;
- memset(buf, 0, sizeof(buf));
- Receive(socket, buf, sizeof(buf));
- if(proxyans->VN == 0 && proxyans->CD == 90)
- {
- return SUCCESS;
- }
- else
- {
- return CONNECT_SERVER_FAIL;
- }
- }
- ProxyStatus CProxy::ConnectBySock5(SOCKET socket, string ip, u_short port)
- {
- char buf[512];
- struct TSock5req1 *proxyreq1;
- proxyreq1 = (struct TSock5req1 *)buf;
- proxyreq1->Ver = 5;
- proxyreq1->nMethods = 1;
- proxyreq1->Methods = m_proxyUserName != "" ? 2 : 0;
- Send(socket, buf, 3);
- struct TSock5ans1 *proxyans1;
- proxyans1 = (struct TSock5ans1 *)buf;
- memset(buf, 0, sizeof(buf));
- Receive(socket, buf, sizeof(buf));
- if(proxyans1->Ver != 5 || (proxyans1->Method != 0 && proxyans1->Method != 2))
- {
- return CONNECT_SERVER_FAIL;
- }
- if(proxyans1->Method == 2)
- {
- int nUserLen = m_proxyUserName.length();
- int nPassLen = m_proxyUserPwd.length();
- //struct TAuthreq *authreq;
- //authreq = (struct TAuthreq *)buf;
- //authreq->Ver = 1;
- //authreq->Ulen = nUserLen;
- //strcpy(authreq->Name, m_proxyUserName.c_str());
- //authreq->PLen = nPassLen;
- //strcpy(authreq->Pass, m_proxyUserPwd.c_str());
- buf[0] = 1;
- buf[1] = nUserLen;
- memcpy(buf + 2, m_proxyUserName.c_str(), nUserLen);
- buf[2 + nUserLen] = nPassLen;
- memcpy(buf + 3 + nUserLen, m_proxyUserPwd.c_str(), nPassLen);
- Send(socket, buf, 3 + nUserLen + nPassLen);
- struct TAuthans *authans;
- authans = (struct TAuthans *)buf;
- memset(buf, 0, sizeof(buf));
- Receive(socket, buf, sizeof(buf));
- if(authans->Ver != 1 || authans->Status != 0)
- {
- return CONNECT_SERVER_FAIL;
- }
- }
- memset(buf, 0, sizeof(buf));
- struct TSock5req2 *proxyreq2;
- proxyreq2 = (struct TSock5req2 *)buf;
- proxyreq2->Ver = 5;
- proxyreq2->Cmd = 1;
- proxyreq2->Rsv = 0;
- proxyreq2->Atyp = 1;
- unsigned long tmpLong = inet_addr(ip.c_str());
- unsigned short port1 = ntohs(port);
- memcpy((char*)&proxyreq2->other, &tmpLong, 4);
- memcpy((char*)(&proxyreq2->other) + 4, &port1, 2);
- //Send(socket, buf, sizeof(struct TSock5req2) + 5);
- Send(socket, buf, 10);
- struct TSock5ans2 *proxyans2;
- memset(buf ,0, sizeof(buf));
- proxyans2 = (struct TSock5ans2 *)buf;
- Receive(socket, buf, sizeof(buf));
- if(proxyans2->Ver != 5 || proxyans2->Rep != 0)
- {
- return CONNECT_SERVER_FAIL;
- }
- return SUCCESS;
- }
- int CProxy::Receive(SOCKET socket, char* buf, int bufLen)
- {
- return recv(socket, buf, bufLen, 0);
- }
- bool CProxy::Send(SOCKET socket, const char* buf, int len)
- {
- long ilen = len;
- int sendCnt = 0;
- int ret;
- while(sendCnt < ilen)
- {
- if((ret = send(socket, buf + sendCnt, ilen - sendCnt, 0)) == SOCKET_ERROR)
- {
- return false;
- }
- else
- {
- sendCnt += ret;
- }
- }
- return true;
- }
proxy中用到的CBase64类
头文件
- #pragma once
- #include <string>
- using namespace std;
- class CBase64
- {
- private:
- CBase64(void);
- public:
- ~CBase64(void);
- static string Encode(const unsigned char* Data,int DataByte);
- static string Decode(const char* Data,int DataByte,int& OutByte);
- };
实现文件
- #include "StdAfx.h"
- #include "Base64.h"
- CBase64::CBase64(void)
- {
- }
- CBase64::~CBase64(void)
- {
- }
- string CBase64::Encode(const unsigned char* Data,int DataByte)
- {
- //编码表
- const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- //返回值
- string strEncode;
- unsigned char Tmp[4]={0};
- int LineLength=0;
- for(int i=0;i<(int)(DataByte / 3);i++)
- {
- Tmp[1] = *Data++;
- Tmp[2] = *Data++;
- Tmp[3] = *Data++;
- strEncode+= EncodeTable[Tmp[1] >> 2];
- strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
- strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
- strEncode+= EncodeTable[Tmp[3] & 0x3F];
- if(LineLength+=4,LineLength==76) {strEncode+=" ";LineLength=0;}
- }
- //对剩余数据进行编码
- int Mod=DataByte % 3;
- if(Mod==1)
- {
- Tmp[1] = *Data++;
- strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
- strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
- strEncode+= "==";
- }
- else if(Mod==2)
- {
- Tmp[1] = *Data++;
- Tmp[2] = *Data++;
- strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
- strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
- strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
- strEncode+= "=";
- }
- return strEncode;
- }
- string CBase64::Decode(const char* Data,int DataByte,int& OutByte)
- {
- //解码表
- const char DecodeTable[] =
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 62, // '+'
- 0, 0, 0,
- 63, // '/'
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
- 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
- 0, 0, 0, 0, 0, 0,
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
- };
- //返回值
- string strDecode;
- int nValue;
- int i= 0;
- while (i < DataByte)
- {
- if (*Data != ' ' && *Data!=' ')
- {
- nValue = DecodeTable[*Data++] << 18;
- nValue += DecodeTable[*Data++] << 12;
- strDecode+=(nValue & 0x00FF0000) >> 16;
- OutByte++;
- if (*Data != '=')
- {
- nValue += DecodeTable[*Data++] << 6;
- strDecode+=(nValue & 0x0000FF00) >> 8;
- OutByte++;
- if (*Data != '=')
- {
- nValue += DecodeTable[*Data++];
- strDecode+=nValue & 0x000000FF;
- OutByte++;
- }
- }
- i += 4;
- }
- else// 回车换行,跳过
- {
- Data++;
- i++;
- }
- }
- return strDecode;
- }