IdMappedPortTCP停用问题

时间:2014-02-02 12:21:04

标签: delphi indy10

我有一个不支持代理访问互联网的外部程序,但我需要代理。

作为解决方案,我使用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之前,是否需要手动执行任何操作?

感谢。

1 个答案:

答案 0 :(得分:0)

Indy服务器是多线程的。他们的事件(如OnConnectOnDisconnectOnExecuteOnExceptionOnListenException)是在工作线程的上下文中触发的,而不是主要的上下文UI线程。因此,您必须与主线程同步,例如使用TThread.Synchronize()TThread.Queue()方法或Indy的TIdSyncTIdNotify类,以便安全地访问UI组件

如果主线程忙于停用服务器,则它无法处理同步请求,因此采用异步方法(TThread.Queue()TIdNotify}优先于同步(TThread.Synchronize()TIdSync)以避免死锁。或者,在工作线程中停用服务器,以便主线程可以自由处理同步请求。