【问题标题】:Indy Version : DELPHI 2010 doesn't recognize some indy classesIndy 版本:DELPHI 2010 无法识别某些 indy 类
【发布时间】:2015-11-23 10:48:36
【问题描述】:

每个人。 我有一个Mr Remy Lebeau 给我的示例代码。 那是关于印地服务器...... 但是,此代码不适用于我的 Delphi 环境。 我的delphi版本是2010,Indy版本通知10.5.5

我的 delphi 无法识别 TIdThreadSafeObjectList, TIdContextThreadList

type
  TMonitorContext = class(TIdServerContext)
  public
    Screenshots: TIdThreadSafeObjectList;
    ScreenshotEvent: THandle;
    constructor Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TIdContextThreadList = nil); override;
    destructor Destroy; override;
  end;

  TScreenshotInfo = class
  public
    ClientIP: string;
    ClientPort: TIdPort;
    Data: TMemoryStream;
    constructor Create;
    destructor Destroy; override;
  end;

constructor TMonitorContext.Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TIdContextThreadList);
begin
  inherited;
  Screenshots := TIdThreadSafeObjectList.Create;
  Screenshots.OwnsObjects := True;
  ScreenshotEvent := CreateEvent(null, True, False, nil);
end;

destructor TMonitorContext.Destroy;
begin
  Screenshots.Free;
  CloseHandle(ScreenshotEvent);
  inherited;
end;

constructor TScreenshotInfo.Create;
begin
  inherited;
  Data := TMemoryStream.Create;
end;

destructor TScreenshotInfo.Destroy;
begin
  Data.Free;
  inherited;
end;

{one side----idTCPServerRecv is to receive screenshot streams from clients}

procedure TIndyServerForm.IdTCPServer_RecvExecute(AContext: TIdContext);
var
  recv_stream: TMemoryStream;
  monitors, queue: TList;
  i: Integer;
  screenshot: TScreenshotInfo;
  monitor: TMonitorContext;
begin
  recv_stream := TMemoryStream.Create;
  try
    if not ReceiveStream(AContext, recv_stream) then
    begin
      ROutMsg := AContext.Binding.PeerIP + ' -> receiving failed: ' + IntToStr(recv_Stream.Size) + ' byte';
      Exit;
    end;
    if recv_Stream.Size < 1024 then
    begin
      recv_Stream.Position := 0;
      ROutMsg := AContext.Binding.PeerIP + ' -> captionString received(' + 
                IntToStr(recv_Stream.Size) + ' byte) : "' + StringFromStream(recv_Stream) + '"';
    end
    else
    begin
      ROutMsg := AContext.Binding.PeerIP + ' -> screenshot received: ' + KBStr(recv_Stream.Size) + ' KB';

      monitors := IdTCPServer_Send.Contexts.LockList;
      try
        // alternatively, only queue the screenshot to particular monitors
        // that are actually interested in this client...
        for i := 0 to monitors.Count-1 do
        begin
          monitor := TMonitorContext(monitors[i]);
          screenshot := TScreenshotInfo.Create;
          try
            recv_Stream.Position := 0;
            screenshot.Data.CopyFrom(recv_stream, 0);
            screenshot.Data.Position := 0;
            queue := monitor.Screenshots.LockList;
            try
              queue.Add(screenshot);
              SetEvent(monitor.ScreenshotEvent);
            finally
              monitor.Screenshots.UnlockList;
            end;
          except
            screenshot.Free;
          end;
        end;
      finally
        IdTCPServer_Send.Contexts.UnlockList;
      end;
    end;
  finally
    recv_stream.Free;
  end;
end;

{another side----idTCPServerSend is to send screenshot streams to monitors}

procedure TIndyServerForm.FormCreate(Sender: TObject);
begin
  IdTCPServer_Send.ContextClass := TMonitorContext;
end;

procedure TIndyServerForm.IdTCPServer_SendExecute(AContext: TIdContext);
var
  monitor: TMonitorContext;
  queue: TList;
  i: Integer;
  screenshot: TScreenshotInfo;
begin
  monitor := TMonitorContext(AContext);
  if WaitForSingleObject(monitor.ScreenshotEvent, 1000) <> WAIT_OBJECT_0 then Exit;
  screenshot := nil;
  try
    queue := monitor.Screenshots.LockList;
    try
      if queue.Count > 0 then
      begin
        screenshot := TScreenshotInfo(queue[0]);
        queue.Delete(0);
      end;
      if queue.Count = 0 then
        ResetEvent(monitor.ScreenshotEvent);
    finally
      monitor.Screenshots.UnlockList;
    end;
    if screenshot = nil then Exit;
    // you should send screenshot.ClientIP and screenshot.ClientPort to
    // this monitor so it knows which client the screenshot came from...
    if not SendStream(AContext, screenshot.Data) then
    begin
      SOutMsg := AContext.Binding.PeerIP + ' -> sending failed -> ' + KBStr(screenshot.Data.Size) + ' KB';
      Exit;
    end;
    SOutMsg := AContext.Binding.PeerIP + ' -> sending successful-> ' + KBStr(screenshot.Data.Size) + ' KB';
  finally
    screenshot.Free;
  end;
end;

我该怎么办? 请帮帮我。

【问题讨论】:

  • 您应该升级到 Indy 版本 >= 10.6。
  • 将 IdContext 和 IdThreadSafe 单元添加到您的使用列表中
  • 当然我已经添加了这些单元。但我的单位不包括以上课程。
  • 应该清楚你需要做什么。您需要使用支持此代码的 Indy 版本。
  • 我的目的只是为了保证 IndyServerthreads 之间的流安全

标签: delphi indy tcpserver


【解决方案1】:

我找到了不升级 Indy 版本的方法...

解决方案如下..

unit UnitServer;


interface

uses
... ... ...

{$IF Declared(TIdContextThreadList) }
// TIdContextThreadList exists
{$ELSE}
type TIdContextThreadList = TThreadList;
{$IFEND}

{$IF Declared(TIdThreadSafeObjectList) }
// TIdThreadSafeObjectList exists
{$ELSE}
type TIdThreadSafeObjectList = TThreadList;
{$IFEND}

type
  TMonitorContext = class(TIdServerContext)
  public
    Screenshots: TIdThreadSafeObjectList;
    ScreenshotEvent: THandle;
    constructor Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TIdContextThreadList = nil); override;
... ... ...
      ... ... ...

如上修改并运行项目,,,, 它运行良好,没有任何问题...

真的很感谢所有给我建议的人... 我要感谢 Remy Lebeau 先生,他给了我重要的指导。

【讨论】:

  • 我给你的原始代码使用TIdThreadSafeObjectList.OwnsObjects 功能进行清理。 TThreadList 类没有这样的特性。通过将TIdThreadSafeObjectList 定义为TThreadList 的别名,您将在TMonitorContext 析构函数中引入微妙的内存泄漏。当上下文被销毁时,您需要释放仍在Screenshots 列表中的所有对象。
  • 我觉得你的回答是对的...因为当只有一个monitor和一个sender时,服务器运行良好...但是当senders和monior增加时,服务器内存消耗增加... . 现在了解原因...谢谢
  • 所以我想改变我的delphi版本...如果只有版本更新Indy对我来说也是一个好方法,对于这种情况,,,通过搜索,Indy版本升级方法对我来说很难.所以我决定改变 Delphi .... 我现在有 Delphi XE8 和 Delphi 2010。 Delphi XE8 适合你的代码???
猜你喜欢
  • 2016-10-19
  • 1970-01-01
  • 2012-02-23
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多