将 Delphi 代码的 Indy 10 写入 C ++ Builder 的 Indy 10
Write the Indy 10 of Delphi Codes's to C ++ Builder's Indy 10
我是C++ Builder的新手。三天前,我安装了 Embarcadero®。 C++Builder® 2010。这门语言对我来说很有趣。
在Delphi中,我通常使用 Indy 9 和 10 的 TIdMappedPortTCP 编写一个简单的代理服务器。我通常使用它的 OnExecute 和 OnOutboundData 事件来修改通过代理的数据。
由于我是 C++ Builder 的新手,所以我不知道如何将我的 Delphi 代码转换为完全正确的 C++ Builder 代码。
我尝试了很多方法,包括阅读了几本书,其中一本是 Borland C++ Builder - The Complete Reference,作者 Herbert Schildt,还有增长知识。不幸的是,书中根本没有讨论与我的情况有关的非常重要的事情。另外,我在 google 上找到了参考资料,但我没有找到。
所以,我冒昧地求助于您。我真的需要它。
请帮忙!非常感谢。
下面是我的 Indy 10 的 Delphi 代码,我想写到 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;
......
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;
*/
}
Update:您链接的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);
}
}
我是C++ Builder的新手。三天前,我安装了 Embarcadero®。 C++Builder® 2010。这门语言对我来说很有趣。
在Delphi中,我通常使用 Indy 9 和 10 的 TIdMappedPortTCP 编写一个简单的代理服务器。我通常使用它的 OnExecute 和 OnOutboundData 事件来修改通过代理的数据。
由于我是 C++ Builder 的新手,所以我不知道如何将我的 Delphi 代码转换为完全正确的 C++ Builder 代码。
我尝试了很多方法,包括阅读了几本书,其中一本是 Borland C++ Builder - The Complete Reference,作者 Herbert Schildt,还有增长知识。不幸的是,书中根本没有讨论与我的情况有关的非常重要的事情。另外,我在 google 上找到了参考资料,但我没有找到。
所以,我冒昧地求助于您。我真的需要它。 请帮忙!非常感谢。
下面是我的 Indy 10 的 Delphi 代码,我想写到 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;
......
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;
*/
}
Update:您链接的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);
}
}