2015-06-27 99 views
0

我是學習C++ Builder的新手。三天前,我安裝了Embarcadero®。 C++Builder®2010.這種語言對我來說非常有趣。將Delphi代碼的Indy 10寫入C++ Builder的Indy 10

在Delphi中,我通常使用Indy 9和10的TIdMappedPortTCP編寫一個簡單的代理服務器。我通常使用它的OnExecute和OnOutboundData事件修改通過代理的數據。

因爲我是C++ Builder中的新成員,所以我不知道如何將我的Delphi代碼轉換爲完全正確的C++ Builder代碼。

我試過和嘗試過很多辦法,包括讀幾本書,其中之一是的Borland C++ Builder中 - 完整的參考,通過赫伯特·希,以及增加知識。不幸的是,在這本書中並沒有討論與我的狀況有關的所有非常重要的事情。此外,我找到谷歌的參考,但我沒有找到。

所以,我冒昧地尋求你的幫助。我真的需要它。 請幫忙!非常感謝你。

以下是我想要寫入C++ Builder的Indy 10的Delphi代碼。

...... 

procedure TForm.IdMappedPortTCP1Execute(AContext: TIdContext); 
var 
Mydata, NetData: string; 
begin 
    if (Pos('HTTP',netstring(AContext)) <> 0) or (Pos('GET',netstring(AContext)) <> 0) then begin 
    NetData := netstring(AContext); 
    TIdMappedPortContext(AContext).OutboundClient.IOHandler.Write(AddHeader(netstring(AContext),'Connection: Keep-Alive')); 
    Sleep(1000); 
    Mydata := 'GET http://website.com/ HTTP/1.1'+#13#10+'Host: website.com'#13#10; 
    NetData := Mydata + Netdata; 
    TIdMappedPortContext(AContext).NetData := netbyte(Netdata); 
    TIdMappedPortContext(AContext).OutboundClient.IOHandler.Write(netbyte(Mydata + NetData)); 
    end; 
end; 

...... 
+2

也許這不是學習新語言的方式。 –

+1

恕我直言,這是正確的方式之一,先生大衛!... – RzV

+0

我會從語言基礎開始 –

回答

3

一個字面翻譯C++ Builder中應該是這樣的:

...... 

String __fastcall AddHeader(String S, String Header) 
{ 
    S = StringReplace(S, "\r\n\r\n", "\r\n" + Header + "\r\n\r\n", TReplaceFlags() << rfReplaceAll); 
    return S; 
} 

void __fastcall TForm::IdMappedPortTCP1Execute(TIdContext *AContext) 
{ 
    String Mydata, NetData; 

    if ((netstring(AContext).Pos("HTTP") != 0) || (netstring(AContext).Pos("GET") != 0)) 
    { 
     NetData = netstring(AContext); 
     TIdMappedPortContext(AContext)->OutboundClient->IOHandler->Write(AddHeader(netstring(AContext), "Connection: Keep-Alive")); 
     Sleep(1000); 
     Mydata = "GET http://website.com/ HTTP/1.1\r\nHost: website.com\r\n"; 
     NetData = Mydata + Netdata; 
     static_cast<TIdMappedPortContext*>(AContext)->NetData = netbyte(Netdata); 
     static_cast<TIdMappedPortContext*>(AContext)->OutboundClient->IOHandler->Write(netbyte(Mydata + NetData)); 
    } 
} 

...... 

這裏有一個稍微精簡版:

...... 

String __fastcall AddHeader(String S, String Header) 
{ 
    return StringReplace(S, "\r\n\r\n", "\r\n" + Header + "\r\n\r\n", TReplaceFlags() << rfReplaceAll); 
} 

void __fastcall TForm::IdMappedPortTCP1Execute(TIdContext *AContext) 
{ 
    String NetData = netstring(AContext); 
    if ((NetData.Pos("HTTP") != 0) || (NetData.Pos("GET") != 0)) 
    { 
     Sleep(1000); 
     String Mydata = "GET http://website.com/ HTTP/1.1\r\nHost: website.com\r\n" + AddHeader(NetData, "Connection: Keep-Alive"); 
     static_cast<TIdMappedPortContext*>(AContext)->NetData = netbyte(Mydata); 
    } 
} 

...... 

但無論哪種方式,這肯定是不是在Indy中實現可行HTTP代理的可靠方法。實際上,Indy 10爲此目的引入了一個特定的TIdHTTPProxyServer組件。你應該認真考慮使用它,而不是TIdMappedPortTCP。例如,上面可以在TIdHTTPProxyServer做過這樣的:

class TIdHTTPProxyServerContextAccess : public TIdHTTPProxyServerContext 
{ 
public: 
    void SetCommand(String Value) { FCommand = Value; } 
    void SetDocument(String Value) { FDocument = Value; } 
    void SetTarget(String Value) { FTarget = Value; } 
}; 

void __fastcall TForm1.IdHTTPProxyServer1HTTPBeforeCommand(TIdHTTPProxyServerContext *AContext) 
{ 
    static_cast<TIdHTTPProxyServerContextAccess*>(AContext)->SetCommand("GET"); 
    static_cast<TIdHTTPProxyServerContextAccess*>(AContext)->SetTarget ("http://website.com/"); 
    static_cast<TIdHTTPProxyServerContextAccess*>(AContext)->SetDocument("/"); 

    AContext->Headers->Values["Host"] = "website.com"; 
    AContext->Headers->Values["Connection"] = "Keep-Alive"; 

    /* 
    the original code was not changing the Host/Port where the 
    HTTP request was being sent to. But if you needed to, 
    you can do it like this... 

    static_cast<TIdTCPClient*>(AContext->OutboundClient)->Host = "website.com"; 
    static_cast<TIdTCPClient*>(AContext->OutboundClient)->Port = 80; 
    */ 
} 

更新:你鏈接的netstring()netbyte()功能有語法錯誤,並有不必要的開銷(有沒有必要MIME只涉及到將字符串轉換爲字節數組,反之亦然,Indy具有專門用於該目的的功能)。以下是修正版本:

String __fastcall netstring(TIdMappedPortContext* AContext) 
{ 
    return BytesToStringRaw(AContext->NetData); 
} 

TIdBytes __fastcall netbyte(String S) 
{ 
    return ToBytes(S, IndyTextEncoding_8Bit()); 
} 

所以,你可以實際上只是完全消除的功能:

void __fastcall TForm::IdMappedPortTCP1Execute(TIdContext *AContext) 
{ 
    TIdMappedPortContext *ctx = static_cast<TIdMappedPortContext*>(AContext) 
    String NetData = BytesToStringRaw(ctx->NetData); 
    if ((NetData.Pos("HTTP") != 0) || (NetData.Pos("GET") != 0)) 
    { 
     Sleep(1000); 
     String Mydata = "GET http://website.com/ HTTP/1.1\r\nHost: website.com\r\n" + AddHeader(NetData, "Connection: Keep-Alive"); 
     ctx->NetData = ToBytes(Mydata); 
    } 
} 
+0

非常感謝。你的回答對我很有幫助。順便說一句,我仍然有錯誤** [BCC32錯誤] Unit1.cpp(116):E2303類型名稱期望**相關的調用netstring + netbyte函數,你可以看到函數[here](http:// pastebin。 COM/Qq64J7iD)。和我的UNIT.CPP&UNIT.H代碼,你可以查看[here](http://pastebin.com/QiFMfnyE)。你能幫我解決這個問題嗎? – RzV

+0

我更新了我的答案。 –

+0

謝謝,雷米先生。但是,我仍然有兩個錯誤:[[BCC32錯誤] Unit1.cpp(111):E2268調用未定義函數'BytesToStringRaw''和'[BCC32錯誤] Unit1.cpp(118):E2268調用未定義函數'IndyTextEncoding_8Bit' '。 Fyi,我把'#pragma link「IdGlobal」'和'#pragma link「IdGlobalProtocols」'放到我的** unit1.cpp **中,還有#include「IdGlobal.hpp」和'#include「IdGlobalProtocols .hpp「'到** unit1.h **中,但這些錯誤仍然會發生。那麼,我應該使用哪個Indy 10組件? – RzV