原理
HTTP代理服务器中能够提供一种HTTP CONNECT代理服务,能够允许用户建立TCP连接到任何端口。通过CONNECT方法穿透代理的实现方法为:
CONNECT代理服务器的代理端口(如:8080);如果成功返回就可以按照正常的Socket进行通讯。当然在此之前需要先获得代理相关的信息。
如何获取HTTP代理相关信息
程序中是通过读取注册表来获取计算机HTTP代理相关信息的,在注册表的\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings键值下就保存着HTTP代理服务器及端口等信息,
根据该键值下的ProxyEnable值可以判断是否有HTTP代理,没有代理的情况下ProxyEnable值为0。
当然一般情况下程序去中访问该键值可能是受限的,所有就需要获取到访问令牌不受限制的UserSid,使用该UserSid去读取HTTP代理信息。
char tmpBuffer[128] = { 0 };
    ::sprintf(tmpBuffer, "CONNECT %s:%d HTTP/1.1\r\nUser-Agent: Mozilla/4.0\r\nConnection: Keep-Alive\r\n\r\n", ip.c_str(), port);
    Send(tmpBuffer, strlen(tmpBuffer));
    Receive(tmpBuffer, sizeof(tmpBuffer));
实现
头文件
#pragma once
#include <string>
#include <vector>
using namespace std;
class addrinfo;
class CHttpProxy
{
public:
    CHttpProxy(std::string ip, unsigned short port)
        :m_proxyIp(ip), m_proxyPort(port), m_socket(-1)
    {}
    ~CHttpProxy(void);
    void ConnectProxyServer();
    void ConnectServer(std::string ip, unsigned short port);
    bool Send(const char* buf, int len);
    int Receive(char* buf, int bufLen);
    int GetSocket()
    {
        return m_socket;
    }
private:
    std::string m_proxyIp;
    addrinfo* m_addrinfo = nullptr;
    unsigned short m_proxyPort;
    int m_socket;
};
实现
#include "HttpProxy.h"
#include <string.h>
#include <time.h>
#ifdef WIN32
#include <WS2tcpip.h>
#else 
#include <unistd.h>
#include <netdb.h> 
#include <arpa/inet.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>  
#define INVALID_SOCKET -1
#endif
CHttpProxy::~CHttpProxy(void)
{
    if (m_addrinfo)
    {
        freeaddrinfo(m_addrinfo);
    }
}
void CHttpProxy::ConnectProxyServer()
{
    struct sockaddr_in addr;
    m_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (m_socket == INVALID_SOCKET)
    {
        throw CException("Error on creating socket fd");
    }
    
    addrinfo inAddrInfo = { 0 };
    inAddrInfo.ai_family = AF_INET;
    inAddrInfo.ai_socktype = SOCK_STREAM;
    std::string strPort = std::to_string(m_proxyPort);
    if (getaddrinfo(m_proxyIp.c_str(), strPort.c_str(), &inAddrInfo, &m_addrinfo) != 0) // error occurs
    {
        throw CException("Error on calling getadrrinfo().");
    }
    if (connect(m_socket, m_addrinfo->ai_addr, m_addrinfo->ai_addrlen))
    {
        throw CException("Error on calling connect().");
    }
}
void CHttpProxy::ConnectServer(std::string ip, unsigned short port)
{
    if (m_socket == INVALID_SOCKET)
    {
        throw CException("Invalid socket fd");
    }
    char tmpBuffer[128] = { 0 };
    ::sprintf(tmpBuffer, "CONNECT %s:%d HTTP/1.1\r\nUser-Agent: Mozilla/4.0\r\nConnection: Keep-Alive\r\n\r\n", ip.c_str(), port);
    Send(tmpBuffer, strlen(tmpBuffer));
    Receive(tmpBuffer, sizeof(tmpBuffer));
    int mj, mi, code;
    ::sscanf(tmpBuffer, "HTTP/%d.%d %d", &mj, &mi, &code);
    if (code != 200)
    {
        throw CException("http connect emial server faild");
    }
}
int CHttpProxy::Receive(char* buf, int bufLen)
{
    return recv(m_socket, buf, bufLen, 0);
}
bool CHttpProxy::Send(const char* buf, int len)
{
    long ilen = len;
    int sendCnt = 0;
    int ret;
    while (sendCnt < ilen)
    {
        if ((ret = send(m_socket, buf + sendCnt, ilen - sendCnt, 0)) == INVALID_SOCKET)
        {
            return false;
        }
        else
        {
            sendCnt += ret;
        }
    }
    return true;
}
 
  
  
  
 
 
  
  
  
 