Einzelnen Beitrag anzeigen

alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#3

Re: SocketServer & mehrere Clients verwalten

  Alt 16. Aug 2005, 11:26
Ich habe mir dafür eine Klasse geschrieben, sodass die Apps mit Hilfe von mailslots kommunizieren können.
Wenn deine Clients und der Server in einer Domäne hängen, klappt das wunderbar, bei einer Arbeitsgruppe weiss ich es nicht.

Auf meinen Clients habe ich einen mailslot namens 'Rcv' eingerichtet. Ein thread setzt sich drauf und wartet, bis eine Nachricht eingetroffen ist (max 1k), dann wird ein Event abgefeuert. Man kann die mailslots auch pollen, also schauen, ob und wie gross die nachricht ist, dann einen Buffer aufmachen und die Daten dann abholen.

Wenn ich nun zum PC 'FooBar' eine Nachricht schicken will, dann schreibe ich die einfach an:'\\FooBar\.\mailslots\Rcv' und -bups- purzelt sie auf der anderen Seite raus.
Delphi-Quellcode:
///////////////////////////////////////////////////////////////////////////////
// SendMail: Send a Mail 'aMessage' to the Mailslot 'aSlotName' on the //
// Machine 'aComputer' //
///////////////////////////////////////////////////////////////////////////////
Procedure SendMail (aComputer, aSlotName, aMessage : String);
var
  Bytes: DWord;
  aPath : String;
  aHandle : THandle;

begin
  aPath := '\\' + aComputer + '\mailslot\' + aSlotName;
  aHandle := CreateFile(PChar(aPath), GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  try
    if aHandle = INVALID_HANDLE_VALUE then
      Raise EInOutError.CreateFmt('Cannot create mailslot %s\%s',[aComputer,aSlotName])
    else
      If not WriteFile(aHandle, Pointer(aMessage)^, Length(aMessage), Bytes, nil)
   Then Raise EInOutError.CreateFmt('Cannot write to mailslot %s\%s',[aComputer,aSlotName]);
  finally
    if aHandle <> INVALID_HANDLE_VALUE Then
      CloseHandle(aHandle);
    end;
end;
Hier ist der MailReceiver, also ein Thread, der auf eine mail wartet:
Delphi-Quellcode:
///////////////////////////////////////////////////////////////////////////////
// Object : TMailReceiver //
///////////////////////////////////////////////////////////////////////////////
constructor TMailReceiver.Create(aSlotName : String; aMaxLength : Integer);
Var
  aPath : String;

begin
  Inherited Create (True);
  fSlotName := aSlotName;
  fMaxLength := aMaxLength;
  aPath := '\\.\mailslot\' + aSlotName;
  fHandle := CreateMailSlot(PChar(aPath), 0, MAILSLOT_WAIT_FOREVER, nil);
  if fHandle = INVALID_HANDLE_VALUE Then //
    Raise Exception.Create ('Could not create mailslot, slotname already exists');
end;

destructor TMailReceiver.Destroy;
begin
  Terminate;
  CloseHandle (fHandle);
end;

procedure TMailReceiver.DoOnMailReceived;
begin
Try
  if Assigned (fOnMail) And (Length (fMessage)>0 ) Then
    fOnMail (Self, fMessage);
  Except
    End;
end;

procedure TMailReceiver.Execute;
Var
  aSize : DWord;

begin
  While Not Terminated Do Begin
    SetLength (fMessage, fMaxLength);
    if ReadFile(fHandle, PChar(fMessage)^, fMaxLength, aSize, nil) Then
      If not terminated Then
   SetLength (fMessage, aSize);
    if not terminated then
      Synchronize (DoOnMailReceived);
    End
end;

procedure TMailReceiver.Start;
begin
  Resume;
end;

procedure TMailReceiver.Stop;
begin
  Try
    Terminate;
    SetMailslotInfo (fHandle,0);
  Except
    End;
end;
Ach, wenn man als Empfänger ein '*' einträgt, dann wird die Mail an alle PC geschickt (also ein Broadcast).

Du erzeugst den TMailReceiver und startest den mit 'Start' (logisch), z.B. im FormCreate oder DatamoduleCreate.
Im flxrmgfDestroy stoppst du den TMailReceiver und schmeisst in Free technisch weg.

Du kannst natürlich mehrere Mailslots einrichten, sodass Du verschiedene Subsysteme realisieren kannst. Usw.

Das geht natürlich alles bestimmt viel eleganter (per UDP?), aber das ist mir alles zu blöd gewesen. so ist es simpel, überschaubar und funzen tut es auch
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat