Delphi下做HTTP代理的问题,大家请进!(100分)

  • 主题发起人 主题发起人 quharry
  • 开始时间 开始时间
Q

quharry

Unregistered / Unconfirmed
GUEST, unregistred user!
我在网上看到一篇文章,原文是这样的:

=====================================================================
文档名称: 使用INDY的IdMappedPortTCP控件实现动态的HTTP代理服务器
文档类别: [转载]
文档作者: 不详
发布日期: 不详
文档备注: 无

--------------------------------------------------------------------------------

使用INDY的IdMappedPortTCP控件实现动态的HTTP代理服务器


在工作中,需要一个时间控制条件非常复杂的代理服务器,因此只能自编。从网络中找到一些用ServerSocket和ClientSocket开发的代理服务器源代码,比较复杂。因此想用INDY控件组中的IdMappedPortTC开发代理服务器。DELPHI附带例子演示的是一个静态的代理,比如例中的www.borland.com,而实际应用中需要的却一个动态的代理。本文即介绍如何使用INDY的IdMappedPortTCP控件实现动态的HTTP代理服务器
分析INDY9所带的源代码,发现NETDATA属性中了存放用户的请求内容和服务器的回复信息,OnExecute事件是在接收到用户请求后与向WEB服务器转发请求之前执行的。因此可以在OnExecute事件写些根据用户的请求更改代理主机的代码,这样就可实现动态代理。
代码如下:
procedure TForm1.IdMappedPortTCP1Execute(AThread: TIdMappedPortThread);
var
RequestHost:string;
RequestPort:integer;
begin
//改变连接
[Red]IDLock.Acquire;[/Red]
try
RequestHost:=GetHost(AThread.NetData);
RequestPort:=GetPort(AThread.NetData);
if (RequestHost<>IdMappedPortTcp1.MappedHost) or
(RequestPort<>IdMappedPortTcp1.MappedPort) then
begin
IdMappedPortTCP1.MappedHost:=RequestHost;
IdMappedPortTCP1.MappedPort:=RequestPort;
TidTcpClient(AThread.OutboundClient).Host:=RequestHost;
TidTcpClient(AThread.OutboundClient).Port:=RequestPort;
TidTcpClient(AThread.OutboundClient).Disconnect;
TidTcpClient(AThread.OutboundClient).Connect(AThread.ConnectTimeOut);
end; //ChangeConnect
finally
[Red]IDLock.Release;[/Red]
end;
end;

实际应用中,访问www.163.com和www.sina.com.cn网站会出现错误,经分析发现需对浏览器的请求格式作些调整,即删除GET请求中的主机名。 在该事件中再加一行改变请求的代码,如下:
//改变请求
AThread.NetData:=DelHostOfURL(AThread.NetData,RequestHost,RequestPort);
上述方法实现HTTP代理服务器非常简单,不信你试试。本次工作的一个重要体会就是分析源代码比看手册资料更有效。
砍死微软,开放源代码万岁!

附:本程序所需的三个自定义函数的代码。
1.获取主机名
function GetHost(URL: string):string;
var
LURI:TIdURI;
begin
LURI:=TIdURI.Create(URL);
result:=LURI.Host;
LURI.Free;
end; //GetHost

2.获取端口号
function GetPort(URL: string):integer;
var
LURI:TIdURI;
begin
LURI:=TIdURI.Create(URL);
if Length(LURI.Port)<>0 then
result:=StrToInt(LURI.Port)
else
result:=80;
LURI.Free;
end; //GetPort

3.删除URL中的HOST字符串
function DelHostOfURL(URL,Host:string;Port:integer):string;
var
s:string;
begin
result:= URL;

s:='http://'+Host;
if Port <> 80 then
s:= s + ':' + IntToStr(Port);

Delete(result,pos(s,result),length(s));
end; //DelHostOfURL

==================================================================
小弟不明白,文中的IDLock是个什么控件???
请大家指点!
 
没有高手愿意指点吗???
[:(]
 
我估计是多线成的那种
TCriticalSection
 
还是不明白,各位大哥能不能回答详细一点啊!
 
哎,没人理我了!
 
《深入DELPHI网络编程》一书中曾经说过编写HTTP代理。
我参照此书写了一个HTTP代理,没有用到控件,代码在如下连接。希望对大家有用
ftp://61.187.64.68/HTTP.rar
 
我就寫了個代理軟件用indy控件,不用一行代碼就搞寫了,而且還很穩定,也可以作代理的代理。
 
springson兄,不知你使用的是哪个控件啊?
 
TIdMappedPortTCP控件,你只要設其屬性就可以了。你可以到indy網站去下demos,然後運行其proxy的例子就可以了。
 
to truest9,
你写的那个HTTP代理有点小问题,
1.就是最多能实现两条线程;
2.就是当客户端断开之后不会自动关闭已开启的线程。
我是新手,不知说得对不对!
谢谢! :)
 
to springson,
据我所知TIdMappedPortTCP控件只能实现静态代理,就是必须先指定要访问的网址才能实现代理功能,对其它网址概概不受理!
不知你是怎样设置属性的,可否告知?
谢谢!
 
這幾天大富翁怎麼老上不了。
只要設置幾個屬性就可以了,比如我的就是:通過192.168.1.254的端口80代理(能直接上網的可不用),然後以本機的8090開放,這樣本機或其它電腦就可以用本機的IP和8090代理上網的了。
object IdMappedPortTCP1: TIdMappedPortTCP
Active = True
Bindings = <
item
Port = 8090
end>
CommandHandlers = <>
DefaultPort = 81
Greeting.NumericCode = 0
MaxConnectionReply.NumericCode = 0
ReplyExceptionCode = 0
ReplyTexts = <>
ReplyUnknownCommand.NumericCode = 0
MappedHost = '192.168.1.254'
MappedPort = 80
Left = 120
Top = 8
end
 
to springson,
你这样只能做为二级代理使用,因为你的远程主机IP和端口已经指定了,做一级代理使用时,只能访问你认定的IP。如:MappedHost = 'www.sohu.com',那么你只能通过它访问sohu网站。
 
你就不要設其屬性試試,實在不行的話,就完全找自己的上網端口試試,這樣也會有轉發的。還不行就看其原代碼是如何實現的。
 
from: http://www.138soft.com/htm/softtip/othertip/006.html
文档名称: 使用INDY的IdMappedPortTCP控件实现动态的HTTP代理服务器
文档类别: [转载]
文档作者: 不详
发布日期: 不详
文档备注: 无
使用INDY的IdMappedPortTCP控件实现动态的HTTP代理服务器


在工作中,需要一个时间控制条件非常复杂的代理服务器,因此只能自编。从网络中找到一些用ServerSocket和ClientSocket开发的代理服务器源代码,比较复杂。因此想用INDY控件组中的IdMappedPortTC开发代理服务器。DELPHI附带例子演示的是一个静态的代理,比如例中的www.borland.com,而实际应用中需要的却一个动态的代理。本文即介绍如何使用INDY的IdMappedPortTCP控件实现动态的HTTP代理服务器
分析INDY9所带的源代码,发现NETDATA属性中了存放用户的请求内容和服务器的回复信息,OnExecute事件是在接收到用户请求后与向WEB服务器转发请求之前执行的。因此可以在OnExecute事件写些根据用户的请求更改代理主机的代码,这样就可实现动态代理。
代码如下:
procedure TForm1.IdMappedPortTCP1Execute(AThread: TIdMappedPortThread);
var
RequestHost:string;
RequestPort:integer;
begin
//改变连接
IDLock.Acquire;
try
RequestHost:=GetHost(AThread.NetData);
RequestPort:=GetPort(AThread.NetData);
if (RequestHost<>IdMappedPortTcp1.MappedHost) or
(RequestPort<>IdMappedPortTcp1.MappedPort) then
begin
IdMappedPortTCP1.MappedHost:=RequestHost;
IdMappedPortTCP1.MappedPort:=RequestPort;
TidTcpClient(AThread.OutboundClient).Host:=RequestHost;
TidTcpClient(AThread.OutboundClient).Port:=RequestPort;
TidTcpClient(AThread.OutboundClient).Disconnect;
TidTcpClient(AThread.OutboundClient).Connect(AThread.ConnectTimeOut);
end; //ChangeConnect
finally
IDLock.Release;
end;
end;

实际应用中,访问www.163.com和www.sina.com.cn网站会出现错误,经分析发现需对浏览器的请求格式作些调整,即删除GET请求中的主机名。 在该事件中再加一行改变请求的代码,如下:
//改变请求
AThread.NetData:=DelHostOfURL(AThread.NetData,RequestHost,RequestPort);
上述方法实现HTTP代理服务器非常简单,不信你试试。本次工作的一个重要体会就是分析源代码比看手册资料更有效。
砍死微软,开放源代码万岁!

附:本程序所需的三个自定义函数的代码。
1.获取主机名
function TForm1.GetHost(URL: string):string;
var
LURI:TIdURI;
begin
LURI:=TIdURI.Create(URL);
result:=LURI.Host;
LURI.Free;
end; //GetHost

2.获取端口号
function TForm1.GetPort(URL: string):integer;
var
LURI:TIdURI;
begin
LURI:=TIdURI.Create(URL);
if Length(LURI.Port)<>0 then
result:=StrToInt(LURI.Port)
else
result:=80;
LURI.Free;
end; //GetPort

3.删除URL中的HOST字符串
function TForm1.DelHostOfURL(URL,Host:string;Port:integer):string;
var
s:string;
begin
result:= URL;

s:='http://'+Host;
if Port <> 80 then
s:= s + ':' + IntToStr(Port);

Delete(result,pos(s,result),length(s));
end; //DelHostOfURL
 
to springson,
你这个就是我在楼上贴的那篇文章啊,
我就是不知道其中那个IdLock是什么?
你知道吗?
可否告知???
谢谢! :)
 
不好意思,我還以為找到答案了呢。我找了下,並沒有這種控件,大概是作者自己寫的線程安全的那種函數。不要也不要緊。你看在開始和結尾才有,應該是不大影響程序的。
IDLock.Acquire;
try
代碼
finally
IDLock.Release;
end;
 
好,我试试先!
 
还是不行哦,
郁闷~~
 
呵呵,还是少用控件吧其所长。
参照HTTP协议自己写一个!
 
后退
顶部