您的位置:首页 > 编程语言 > C语言/C++

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

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

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

头文件

[cpp] view
plaincopy

#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;

};

实现文件

[cpp] view
plaincopy

#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类

头文件

[cpp] view
plaincopy

#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);

};

实现文件

[cpp] view
plaincopy

#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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: