程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 基於 POCO 框架的 C++ 版搜狗代理程序

基於 POCO 框架的 C++ 版搜狗代理程序

編輯:C++入門知識

搜狗代理服務器程序,網上已經有用 Python 實現的版本。這個版本在某些情況下(例如迅雷下載)性能不夠好,於是我用 C++ 實現了一個版本,基於 POCO 框架開發,應當具有不錯的可移植性(改一下 _snprintf 函數名)。完整的源代碼如下:
[Cpp] 
#include <stdio.h> 
#include <time.h> 
#include <vector> 
#include <string> 
#include <Poco/ErrorHandler.h> 
#include <Poco/Net/Socket.h> 
#include <Poco/Net/HTTPServer.h> 
#include <Poco/Net/HTTPServerRequest.h> 
#include <Poco/Net/HTTPServerRequestImpl.h> 
#include <Poco/Net/HTTPServerResponse.h> 
#include <Poco/Net/HTTPRequestHandler.h> 
#include <Poco/Net/HTTPClientSession.h> 
 
using namespace std; 
using namespace Poco; 
using namespace Poco::Net; 
 
class EH : public ErrorHandler 

    virtual void exception(const Exception& exc) 
    { 
        printf("%s: %s\n", exc.what(), exc.message().c_str()); 
    } 
 
    virtual void exception(const std::exception& exc) 
    { 
        printf("%s\n", exc.what()); 
    } 
 
    virtual void exception() 
    { 
        printf("Unknown exception\n"); 
    } 
}; 
 
const int BUFFER_SIZE = 65536; 
 
class ProxyService : public HTTPRequestHandler 

    HTTPClientSession client; 
 
    static unsigned int hashTag(const string &s) 
    { 
        unsigned int code = s.length(); 
        for (int i = 0; i < s.length() / 4; ++i) 
        { 
            unsigned int a = (s[i * 4] & 0xffu) + ((s[i * 4 + 1] & 0xffu) << 8); 
            unsigned int b = (s[i * 4 + 2] & 0xffu) + ((s[i * 4 + 3] & 0xffu) << 8); 
            code += a; 
            code ^= ((code << 5) ^ b) << 0xb; 
            code += code >> 0xb; 
        } 
        switch (s.length() % 4) 
        { 
        case 1: 
            code += s[s.length() - 1] & 0xffu; 
            code ^= code << 0xa; 
            code += code >> 1; 
            break; 
        case 2: 
            code += (s[s.length() - 2] & 0xffu) + ((s[s.length() - 1] & 0xffu) << 8); 
            code ^= code << 0xb; 
            code += code >> 0x11; 
            break; 
        case 3: 
            code += (s[s.length() - 3] & 0xffu) + ((s[s.length() - 2] & 0xffu) << 8); 
            code ^= (code ^ ((s[s.length() - 1] & 0xffu) << 2)) << 0x10; 
            code += code >> 0xb; 
            break; 
        } 
        code ^= code << 3; 
        code += code >> 5; 
        code ^= code << 4; 
        code += code >> 0x11; 
        code ^= code << 0x19; 
        code += code >> 6; 
        return code; 
    } 
 
    static string hexString(unsigned int x) 
    { 
        char buff[20]; 
        _snprintf(buff, 16, "%08x", x); 
        return string(buff, buff + 8); 
    } 
 
    void write(istream &in, ostream &out) 
    { 
        char buffer[BUFFER_SIZE]; 
        streamsize sz; 
        while (in.good() && out.good()) 
        { 
            in.read(buffer, sizeof(buffer)); 
            sz = in.gcount(); 
            if (sz <= 0) 
                break; 
            if (out.good()) 
                out.write(buffer, sz); 
        } 
    } 
 
public: 
    ProxyService() 
    { 
        static char xid = '0'; 
        char host[] = "h0.edu.bj.ie.sogou.com"; 
        char id = xid + 1; 
        if (id > '9') 
            id = '0'; 
        host[1] = id; 
        xid = id; 
        client.setHost(host); 
        client.setPort(80); 
    } 
 
    virtual void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) 
    { 
        static const string authToken = "5FA7CF6A1809B3B514FA66A1ECA16FEB/30/78e7ff933a9a3063"; 
        string timestamp(hexString((unsigned)time(0))); 
        string tag(hexString(hashTag(timestamp + request.getHost() + "SogouExplorerProxy"))); 
        try 
        { 
            HTTPRequest clientRequest(request.getMethod(), request.getURI(), request.getVersion()); 
            for (NameValueCollection::ConstIterator i = request.begin(); i != request.end(); ++i) 
                clientRequest.set(i->first, i->second); 
            clientRequest.set("X-Sogou-Auth", authToken); 
            clientRequest.set("X-Sogou-Tag", tag); 
            clientRequest.set("X-Sogou-Timestamp", timestamp); 
            ostream& os = client.sendRequest(clientRequest); 
            os.flush(); 
            if (toUpper(request.getMethod()) == "POST") 
            { 
                write(request.stream(), os); 
                os.flush(); 
            } 
 
            HTTPResponse clientResponse; 
            istream& is = client.receiveResponse(clientResponse); 
            response.setStatusAndReason(clientResponse.getStatus(), clientResponse.getReason()); 
            for (NameValueCollection::ConstIterator i = clientResponse.begin(); i != clientResponse.end(); ++i) 
                response.set(i->first, i->second); 
            ostream& out = response.send(); 
            out.flush(); 
            if (toUpper(request.getMethod()) == "CONNECT" && clientResponse.getStatus() == HTTPResponse::HTTP_OK) 
            { 
                char buffer[BUFFER_SIZE]; 
                int sz; 
                istream &in = request.stream(); 
 
                sz = (int)is.readsome(buffer, sizeof(buffer)); 
                if (sz > 0) 
                { 
                    out.write(buffer, sz); 
                    out.flush(); 
                } 
                sz = (int)in.readsome(buffer, sizeof(buffer)); 
                if (sz > 0) 
                { 
                    os.write(buffer, sz); 
                    os.flush(); 
                } 
 
                StreamSocket s1 = client.socket(); 
                StreamSocket s2 = ((HTTPServerRequestImpl*)&request)->socket(); 
                vector<Socket> list, l2, l3; 
                while (true) 
                { 
                    list.clear(); 
                    list.push_back(s1); 
                    list.push_back(s2); 
                    Socket::select(list, l2, l3, Timespan(20, 0)); 
                    if (list.empty()) 
                        break; 
                    if (list[0] == s2) 
                    { 
                        sz = s2.receiveBytes(buffer, sizeof(buffer)); 
                        if (sz <= 0) 
                            break; 
                        s1.sendBytes(buffer, sz); 
                    } 
                    else 
                    { 
                        sz = s1.receiveBytes(buffer, sizeof(buffer)); 
                        if (sz <= 0) 
                            break; 
                        s2.sendBytes(buffer, sz); 
                    } 
                } 
            } 
            else 
            { 
                write(is, out); 
                out.flush(); 
            } 
        } 
        catch (const Exception &) 
        { 
            client.reset(); 
        } 
    } 
}; 
 
class ProxyRequestHandlerFactory : public HTTPRequestHandlerFactory 

public: 
    virtual HTTPRequestHandler *createRequestHandler(const HTTPServerRequest & request) 
    { 
        return new ProxyService; 
    } 
}; 
 
int main(int argc, char **argv) 

    ThreadPool::defaultPool().addCapacity(128 - ThreadPool::defaultPool().capacity()); 
    ServerSocket socket; 
    socket.bind(SocketAddress("127.0.0.1", 8008), true); 
    socket.listen(); 
    HTTPServerParams *params = new HTTPServerParams; 
    params->setMaxThreads(64); 
    params->setServerName("ProxyService"); 
    params->setSoftwareVersion("1.0"); 
    HTTPServer server(new ProxyRequestHandlerFactory(), socket, params); 
    server.start(); 
    while (true) 
    { 
        Thread::sleep(65535); 
    } 
    server.stop(); 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved