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