我有一个不支持代理访问互联网的外部程序,但我需要代理。
作为解决方案,我使用Indy 10.6.0.5040及其TIdMappedPortTCP组件编写了一个简单的Delphi应用程序。它是如何工作的,外部应用程序在本地连接到IdMappedPortTCP,IdMappedPortTCP使用我的代理设置连接到真实服务器。
为了进行我的代理设置,我处理了IdMappedPortTCP的OnConnect事件,如下所示:
procedure TForm1.IdMappedPortTCP1Connect(AContext: TIdContext);
var
io: TIdIOHandlerStack;
proxy: TIdConnectThroughHttpProxy;
begin
if Assigned(TIdMappedPortContext(AContext).OutboundClient) then
begin
io := TIdIOHandlerStack.Create(TIdMappedPortContext(AContext).OutboundClient);
proxy := TIdConnectThroughHttpProxy.Create(io);
proxy.Enabled := False;
proxy.Host := FSettings.ProxyAddress;
proxy.Port := FSettings.ProxyPort;
proxy.Username := FSettings.ProxyUserName;
proxy.Password := FSettings.ProxyPassword;
If (proxy.Username <> '') or (proxy.Password <> '') then proxy.AuthorizationRequired(True);
proxy.Enabled := True;
io.DefaultPort := FSettings.DestinationPort[0];
io.Port := FSettings.DestinationPort[0];
io.Destination := FSettings.DestinationHostAddress[0];
io.Host := FSettings.DestinationHostAddress[0];
io.TransparentProxy := proxy;
io.OnStatus := StackStatus;
TIdMappedPortContext(AContext).OutboundClient.IOHandler := io;
end;
Log(Format('Listener connected at %s:%d', [TIdMappedPortContext(AContext).Server.MappedHost, TIdMappedPortContext(AContext).Server.MappedPort]));
end;
{ TIdConnectThroughHttpProxyHelper }
procedure TIdConnectThroughHttpProxyHelper.AuthorizationRequired(const val: boolean);
begin
Self.FAuthorizationRequired := val;
end;
procedure TForm1.Log(const s: string);
begin
Memo1.Lines.Add(Format('(%s) %s', [FormatDateTime('hh:nn:ss:zzz', Now), s]));
end;
procedure TForm1.IdMappedPortTCP1Disconnect(AContext: TIdContext);
begin
// Log(Format('Listener disconnected at %s:%d', [TIdMappedPortContext(AContext).Server.MappedHost, TIdMappedPortContext(AContext).Server.MappedPort]));
end;
procedure TForm1.IdMappedPortTCP1Exception(AContext: TIdContext;
AException: Exception);
begin
Log(Format('Exception: %s (%s:%d)', [AException.Message,TIdMappedPortContext(AContext).Server.MappedHost, TIdMappedPortContext(AContext).Server.MappedPort]));
end;
procedure TForm1.IdMappedPortTCP1ListenException(AThread: TIdListenerThread;
AException: Exception);
begin
Log(Format('Listener Exception: %s', [AException.Message]));
end;
procedure TForm1.IdMappedPortTCP1OutboundConnect(AContext: TIdContext);
begin
Log('MappedPort Destination connected.');
end;
procedure TForm1.IdMappedPortTCP1OutboundDisconnect(AContext: TIdContext);
begin
Log('MappedPort Destination disconnected.');
end;
procedure TForm1.StackStatus(ASender: TObject;
const AStatus: TIdStatus; const AStatusText: string);
begin
Log(Format('Stack Status: %s', [AStatusText]));
end;
我有许多活跃的联系,所有工作都完美无瑕。我的问题是,如果我尝试使用“IdMappedPortTCP.Active:= false;”停用IdMappedPortTCP虽然有活动流量,连接,它挂起,我不得不使用任务管理器终止delphi应用程序。
在将Active设置为false之前,是否需要手动执行任何操作?
感谢。
答案 0 :(得分:0)
Indy服务器是多线程的。他们的事件(如OnConnect
,OnDisconnect
,OnExecute
,OnException
和OnListenException
)是在工作线程的上下文中触发的,而不是主要的上下文UI线程。因此,您必须与主线程同步,例如使用TThread.Synchronize()
或TThread.Queue()
方法或Indy的TIdSync
或TIdNotify
类,以便安全地访问UI组件
如果主线程忙于停用服务器,则它无法处理同步请求,因此采用异步方法(TThread.Queue()
或
TIdNotify
}优先于同步(TThread.Synchronize()
或TIdSync
)以避免死锁。或者,在工作线程中停用服务器,以便主线程可以自由处理同步请求。