连接到网络中多个设备的应用程序

时间:2014-10-14 19:19:28

标签: multithreading sockets delphi

我的本​​地网络上有一个X号电子设备(气象站)变量,每个设备提供与特定IP和端口的ServerSocket连接,我有一个连接到所有此类设备的应用程序,我的应用程序知道IP和这些设备的端口在数据库中注册,打开我的应用程序,我创建了一个动态[TClientSocket(Array)]连接到这些设备中的每一个,随后改变了很多信息,比如谈话,询问温度所有的设备,他们回答我,或者我可以要求一个温度,湿度到另一个,风速到另一个等......通过内部操作。 今天我做一个FOR循环,所有连接的设备从它知道哪个操作与我的软件设备,然后随机对话与每个装备,但这是缓慢的,因为它增加了设备的数量增加了FOR慢。我做的是删除FOR的线程,我想知道这是否可行。 onConnect,OnRead等...我的TClientScojet事件在创建TClientSocket数组时分配,所以我最终得到了这个,然后使用另一个并且不能同时满足所有设备。 我希望我可以将这个Thread用于所有设备并同时满足,但不要主宰概念和使用,如果有人知道如何改进这些代码,我将非常感激。

今天我使用这个类创建了扩展的TClientSocket:

type
  TTermoCenter = class(TClientSocket)
  private
    countSema: Thandle;
    access: TCriticalSection;
    ...
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Push(inObject: TPalavra; priority: Integer); virtual;
    function Pop(pResObject: pObject; timeout: Integer): Boolean;
  end;

这是构造函数:

constructor TTermoCenter.Create(AOwner: TComponent);
var
  I: Integer;
begin
  inherited;
  access := TCriticalSection.Create;
  ...
end;

这是析构函数:

destructor TTermoCenter.Destroy;
var
  I: Integer;
begin
  ...
  access.Free;
  closeHandle(countSema);
  inherited;
end;

变量声明:

var
  termocenters: array of TTermoCenter;

创建表单时,我定义了数组的大小

SetLength(termocenters, dm.sqlTermocenter.RecordCount);

我根据数据库中的内容创建连接:

var
  SocketTmp: TTermoCenter;

  while not cds.Eof do
  begin
    SocketTmp := TTermoCenter.Create(nil);
    SocketTmp.name := 'cdsNome';
    SocketTmp.Port := 'cdsPorta';
    SocketTmp.ClientType := ctNonBlocking;
    SocketTmp.Host := 'cdsIP';
    // atribui eventos
    SocketTmp.OnRead := TCPRead;
    SocketTmp.OnConnect := TCPConnect;
    SocketTmp.OnDisconnect := TCPDisconnect;
    SocketTmp.OnError := TCPError;

    //Coloca no Array
    termocenters[I] := SocketTmp;
    try
      termocenters[I].Active := True;
      sleep(1000);
    except
      on E: Exception do
        frmMain.mmErros.Lines.Add(TimeToStr(now) + ' - ' + E.ClassName + ' CriaConexao : ' + E.Message);
        end;
      end;
    end;
  cds.Next;
end;
end;

这是我今天的代码的一个很好的总结,我想帮助实现Threads。谢谢。

1 个答案:

答案 0 :(得分:2)

如果您在具有消息循环的线程(例如主UI线程)的上下文中创建TClientSocket对象,则使用TClientSocket事件将正常工作。

您使用的是非阻止模式,因此设置Active=True不会阻止您的循环。连接将在后台进行。当您收到OnConnect事件时,它会告诉您已连接的特定TCustomWinSocket,因此您知道可以开始向哪个特定设备发送命令。如果您收到OnError事件,它会告诉您这是否是连接错误,这样您就可以知道哪些设备无法连接。

触发OnRead时,它会告诉您正在发送数据的特定TCustomWinSocket,因此您知道哪个设备正在报告信息。由于您使用的是非阻塞模式,OnRead事件提供的数据可能(并且通常会)不完整,因此只需将其缓存到某处(例如使用TCustomWinSocket.Data属性保持指向您追加新数据的缓冲区的指针,并仅从缓冲区中提取已完成的消息,以便稍后在缓冲区中保留不完整的消息。对于每个完整的消息,您可以根据需要使用/更新该特定设备的信息。

如果您在使用这些活动时遇到问题,请显示您的实际代码。到目前为止,您所展示的内容还不足以诊断您遇到的任何问题。