2015-06-27 37 views
0

Я новичок в изучении C++ Builder. Три дня назад я установил Embarcadero®. C++ Builder® 2010. Этот язык очень интересен для меня.Напишите Indy 10 из кодеков Delphi в C++ Builder Indy 10

В Delphi я обычно пишу простой прокси-сервер, используя TIdMappedPortTCP Indy 9 и 10. Я обычно использую его события OnExecute и OnOutboundData для изменения данных при прохождении через прокси.

Поскольку я новичок в C++ Builder, поэтому я не знаю, как конвертировать мой код Delphi в точно правильный код C++ Builder.

Я пробовал и пробовал много способов, в том числе чтения нескольких книг, одна из которых является Borland C++ Builder - Полный справочник, по Шилдт, а также для повышения знаний. К сожалению, в книге не обсуждалось совсем не очень важные вещи, связанные с моим состоянием. Кроме того, я нахожу ссылки на Google, но я не нашел.

Итак, я отважился попросить о вашей помощи. Мне это действительно нужно. Пожалуйста, помогите! Большое спасибо.

Следующее - это код Delphi для Indy 10, который я хочу написать в C++ Builder.

...... 

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

...... 

Но в любом случае, это, безусловно, НЕ надежный способ реализации жизнеспособного HTTP-прокси в Indy. Фактически, 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; 
    */ 
} 

Update: в netstring() и netbyte() функции вы связаны иметь синтаксические ошибки, и имеет излишнюю нагрузку (нет необходимости привлекать MIME только преобразовать String в массив байтов и наоборот, 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

Большое спасибо. Ваш ответ мне очень помогает. Btw, я все еще получил ошибку ** [Ошибка BCC32] Unit1.cpp (116): E2303 Ожидаемое имя типа **, связанное с вызывающими функциями netstring + netbyte, вы можете увидеть функцию [здесь] (http: // pastebin. ком/Qq64J7iD). И все мои коды UNIT.CPP & UNIT.H вы можете просмотреть здесь (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