您的位置:首页 > 其它

winsock代理类

2015-10-20 11:03 260 查看
原文地址:/article/9175734.html

代理通常有三种:HTTP、SOCKS4、SOCKS5。HTTP代理可以使用libCurl库来直接使用,其它两种代理一般都需要自己写代码来实现。

头文件

#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\r\nHost: %s:%d\r\nAuthorization: Basic %s\r\n\r\nProxy-Authorization: Basic %s\r\n\r\n",
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\r\nHost: %s:%d\r\n\r\n", ip.c_str(), port, ip.c_str(), port);
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);
}

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+="\r\n";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 != '\r' && *Data!='\n')
{
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: