Newsgroup: it.comp.lang.delphi
Titolo: [D6] ServerSocket e DataModule

Salve,
Qualcuno di voi ha mai avuto problemi ad utilizzare un TServerSocket su un
DataModule?
Da quanto ho visto l'evento OnClientRead non viene mai richiamato se il
componente si
trova sul DM.
Idee?
Andrea

 Idee?
Tanto per dettagliare il contesto, lo usi bloccante? Hai semplicemente
spostato componente e codice che lavoravano su un Form in un DM?
Saluti
Paolo Arosio
--
"La dimostrazione dell'esistenza di specie intelligenti nell'universo
 e' che non ci vengono a trovare"

 Paolo Arosio
Andrea


wrote:

Hai provato a spostarlo su un form ? 

 Hai provato a spostarlo su un form ?
Sul form so già che funziona, ma io non lo voglio sul form, lo voglio sul DM
:-)
E lo voglio sul DM in quanto la funzionalita' di "ascolto" dovrebbe, imho,
essere
separata da quella di "presentazione".
Sto infatti scrivendo il progetto in modo che sul DM principale ci sia la
logica del "motore" con
l'ascolto della porta, mentre sul form principale ci vanno il log ed altre
cose.
Ciaux,
Andrea

essere separata da quella di "presentazione".
Non ho tempo di guardare i sorgenti del componente, ma non vorrei che
il TServerSocket basasse il suo funzionamento sull'handle di finestra
del suo "possessore".  Il datamodule non è una finestra, quindi...

The DeerBear scriveva fra l'altro:
[cut]
Boh, quanto segue a me funziona as expected (provato in lan con W2k,
telnet ms come client)
Pero', son simpatici i socket.
(v. dopo la signature)
Saluti
Paolo Arosio
--
"La dimostrazione dell'esistenza di specie intelligenti nell'universo
 e' che non ci vengono a trovare"
< gestore eventi del DM: sulla main form >
procedure TfrmMainServer.SocketEventHandler(Sender: TObject;
  Kind: TEventKind; const Desc: string);
var l: TStrings;
begin
  l := lbSockets.Items;
  case Kind of
    ekConnect,
    ekDisconnect: dmServer.GetSocketList(l);    // aggiorna lista socket
  end;
  Memo1.Lines.Add(Desc);    // mostra stringa - evento
end;
< Data module >
unit udmServer;
interface
uses
  SysUtils, Classes, ScktComp;
type
  EServerException = class(Exception);
  TEventKind = (ekConnect, ekHelo, ekReceive, ekSend, ekDisconnect,
ekError);
  TSocketEvent = procedure(Sender: TObject;
    Kind: TEventKind; const Desc: string) of object;
  TdmServer = class(TDataModule)
    Server: TServerSocket;
    procedure ServerClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServerClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
    procedure ServerClientRead(Sender: TObject; Socket:
TCustomWinSocket);
  private                          { Private declarations }
    fKind: TEventKind;
    fDesc: string;
    fOnSocketEvent: TSocketEvent;
    fSktList: TStringList;
    function GetActive: boolean;
    procedure SetActive(const Value: boolean);
    function GetPort: integer;
    procedure SetPort(const Value: integer);
  protected
    procedure DoEvent; virtual;
    procedure Helo(aSkt: TCustomWinSocket);
    function IdOfSkt(aSkt: TCustomWinSocket): string;
    function SktFromId(anId: string): TCustomWinSocket;
  public                           { Public declarations }
    property Active: boolean read GetActive write SetActive;
    property Port: integer read GetPort write SetPort;
    property OnSocketEvent: TSocketEvent read fOnSocketEvent write
fOnSocketEvent;
    procedure GetSocketList(out Dest: TStrings);
    procedure SendMessageTo(aClient: string; aMessage: string);
  end;
var
  dmServer: TdmServer;
implementation
{$R *.dfm}
var NextID: integer;
{ TdmServer }
procedure TdmServer.DataModuleCreate(Sender: TObject);
begin
  fSktList := TStringList.Create;
  NextId := 1;
end;
procedure TdmServer.DataModuleDestroy(Sender: TObject);
var i: integer;
begin
  for i := fSktList.Count - 1 downto 0 do begin
    TCustomWinSocket(fSktList.Objects[i]).Close;
  end;
  fSktList.Free;
end;
function TdmServer.GetActive: boolean;
begin
  Result := Server.Active;
end;
function TdmServer.GetPort: integer;
begin
  Result := Server.Port;
end;
procedure TdmServer.SetActive(const Value: boolean);
begin
  Server.Active := Value;
end;
procedure TdmServer.SetPort(const Value: integer);
begin
  if Server.Active then Raise EServerException.Create('Cannot change
Port');
  Server.Port := Value;
end;
procedure TdmServer.ServerClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  fSktList.AddObject('Client ' + inttostr(NextId), Socket);
  inc(NextId);
  fKind := ekConnect;
  fDesc := 'New client: ' + Socket.RemoteHost;
  DoEvent;
  Helo(Socket);
end;
procedure TdmServer.ServerClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
var index: integer;
    Id: string;
begin
  index := fSktList.IndexOfObject(Socket);
  Id := fSktList[index];
  fSktList.Delete(index);
  fKind := ekDisconnect;
  fDesc := Id + ' ' + Socket.RemoteHost + ' disconnected';
  DoEvent;
end;
procedure TdmServer.ServerClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var msg: string;
begin
  msg := Socket.ReceiveText;
  fKind := ekReceive;
  fDesc := IdOfSkt(Socket) + ' ' + Socket.RemoteHost + ': ' + msg;
  DoEvent;
end;
procedure TdmServer.SendMessageTo(aClient, aMessage: string);
begin
  with SktFromId(aClient) do begin
    SendText(aMessage + #13#10);
    fKind := ekSend;
    fDesc := aClient + ' ' + RemoteHost + ': ' + aMessage;
  end;
  DoEvent;
end;
procedure TdmServer.DoEvent;
begin
  if Assigned(fOnSocketEvent) then
    fOnSocketEvent(Self, fKind, fDesc);
end;
procedure TdmServer.Helo(aSkt: TCustomWinSocket);
begin
  aSkt.SendText('HELO ' + 'SimpleTCP Server'#13#10);
  fKind := ekHelo;
  fDesc := 'Helo sent to ' + aSkt.RemoteHost;
end;
procedure TdmServer.GetSocketList(out Dest: TStrings);
begin
  Dest.Clear;
  Dest.AddStrings(fSktList);
end;
function TdmServer.IdOfSkt(aSkt: TCustomWinSocket): string;
var Idx: integer;
begin
  Idx := fSktList.IndexOfObject(aSkt);
  if (Idx < 0) or (idx >= fSktList.Count) then
    Result := ''
  else
    REsult := fSktList.Strings[idx];
end;
function TdmServer.SktFromId(anId: string): TCustomWinSocket;
var Idx: integer;
begin
  Idx := fSktList.IndexOf(anId);
  if (Idx < 0) or (idx >= fSktList.Count) then
    raise EServerException.Create('Socket not found: ' + anId);
  Result := TCustomWinSocket(fSktList.Objects[Idx]);
end;
end.

 (v. dopo la signature)
Ovviamente il contenuto del DM e' un TServerSocket con bindati gli
eventi OnClientConnect, OnClientDisconnect, OnClientRead; dato che il
componente ha nome (originale <g>) Server, i gli handler sono
ServerClientConnect, ServerClientDisconnect, ServerClientRead.
