写代码经常会遇到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:    //HTTPreturn ConnectByHttp(socket, ip, port);break;case 1:    //SOCK4return ConnectBySock4(socket, ip, port);break;case 2:    //SOCK5return 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;
}

socket穿透代理代码(C++版)相关推荐

  1. 穿透代理获取用户真实IP地址

    文章目录 一.场景 二.方法 1.微信官方方法 (1)没有代理 (2)有代理 2.非官方方法 (1)代码 (2)说明 (3)补充 一.场景 在对接微信H5支付API时,有一关键步骤是获取到用户的真实I ...

  2. android socket io和服务器_Java socket通讯服务器和客户端教学版

    什么是socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API), ...

  3. JDK和cglib动态代理代码示例

    JDK和cglib动态代理代码: package com.zhangxueliang.demo.proxy;import java.lang.reflect.InvocationHandler; im ...

  4. php运行socket服务器,PHP_php简单socket服务器客户端代码实例,本篇文章分享一个简单的socket - phpStudy...

    php简单socket服务器客户端代码实例 本篇文章分享一个简单的socket示例,用php.实现一个接收输入字符串,处理并返回这个字符串到客户端的TCP服务. 产生一个 socket 服务端 /*文 ...

  5. python代码实例sicket_Python socket聊天脚本代码实例

    这篇文章主要介绍了Python socket聊天脚本代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 没有前端,多开了一条线程用于接收信息. ...

  6. jquery实现:返回顶部(动画·代码精简版)- 代码篇

    jquery实现:返回顶部(动画·代码精简版):animate 使用css3的animate属性,一行代码就能实现功能. 动画演示(省略) 代码如下:(精简) <script type=&quo ...

  7. java web启动socket_javaweb启动时启动socket服务端代码实现

    这篇文章主要介绍了javaweb启动时启动socket服务端代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 说明:在javaweb项目启动的 ...

  8. 嗜血代码软件测试,噬血代码steam版

    <噬血代码steam版>(Code Vein)是一款探索动作RPG游戏,由<噬神者>团队Bandai Namco采用虚幻4引擎开发.噬血代码由<噬神者>系列总制作人 ...

  9. iOS、Android连接Charles代理(Mac版)

    iOS.Android连接Charles代理(Mac版) 1.软件Charles的下载 网址:https://www.charlesproxy.com/ 选择下载Mac OS版本就行了,待安装完成后 ...

最新文章

  1. 想为企业杜绝钓鱼邮件,ValiMail 获1200万美元A轮融资
  2. MySQL中的Text类型
  3. c++ 异步下获取线程执行结果_【分享吧】C++11多线程库介绍
  4. SSM综合练习功能介绍与项目演示
  5. mysql主从修改系统参数步骤_mysql主从配置的参数配置与步骤_MySQL
  6. android 获取蓝牙设备id_【报Bug】安卓平台获取不到蓝牙设备服务列表(ios可以)...
  7. 使用NGUI来制作技能的CD冷却效果
  8. 使用Android进行VR图像处理
  9. Eclipse 生成WebService客户端代码
  10. 中国“古诗词”数据库还有可用的API
  11. 单层决策树python_基于单层决策树的adaboost算法Python实现
  12. 海外怎么用网易云听歌,网易云音乐国外用不了怎么办
  13. Python学习笔记(一)(图灵学院)
  14. android手机如何设置提高网速,安卓手机网速慢怎么办 安卓手机网速慢解决办法【详解】...
  15. GN+NINJA环境搭建(MacOS Windows)
  16. html ifrme 选择器,html中iframe/css样式设置,id,class选择器的使用规则等学习2019.9.2 08:00...
  17. uva10859放置街灯(树形dp)
  18. QQ网络存储随便用(原创)
  19. 肠胃一直不好,该如何进行调理?
  20. 亚马逊主图视频和买家秀视频有必要做吗?

热门文章

  1. 为什么接口需要加密传输
  2. plsql编程语言定义变量
  3. 格式化输出字符串变量
  4. 基本的SQL-SELECT语句练习
  5. 建造者模式源码解析(jdk-guava+mybatis)
  6. 设计模式之_Strategy_05
  7. oracle解除死锁
  8. ubuntu 安装libusb 编译自己写的程序 发现很多undefined(排除包含头文件的问题)
  9. 解决报错:import sun.misc.BASE64Decoder无法找到
  10. 2017年12月英语四级翻译预测