Autor Beitrag
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 08.05.12 13:58 
Wie kann man andere, laufende Instanzen der eigenen Anwendung im LAN finden?

Ein möglicher Ansatz ist eine Suche per UDP-Broadcast. Da nur im LAN gesucht werden soll (nicht im Internet oder WAN) sollte es keine Probleme mit einem UDP-Broadcast geben (diese werden häufig von Routern ausgefiltert). Für dieses Beispiel wird meine OpenSource-Komponente TUdpSockUtil verwendet.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
uses
  ..., UdpSockUtil, WinSock; // WinSock wird für den Typ in_addr benötigt

const
  SERVICE_PORT   = 12345// hier wartet eine Instanz auf Anfragen
  MY_APP_REQUEST = AnsiString('FindLanInstanceDemo:Request');
  MY_APP_REPLY   = AnsiString('FindLanInstanceDemo:Reply');

// Beim Programmstart die Eigenschaften des UDP-Sockets setzen und öffnen
procedure TfrmMain.FormCreate(Sender: TObject);
begin
  UdpSockUtil1.LocalPort := SERVICE_PORT;
  UdpSockUtil1.RemotePort := SERVICE_PORT;
  UdpSockUtil1.Broadcast := TRUE;
  UdpSockUtil1.Open; // auf eingehende Pakete reagieren
end;

// Andere Instanzen per Rundesendenachricht im LAN suchen
procedure TfrmMain.btnSearchClick(Sender: TObject);
begin
  UdpSockUtil1.BroadcastText(MY_APP_REQUEST);
end;
Bis hier sind nur Voraussetzungen geschaffen worden. Kommen wir nun zum spannenden Teil, wo ein Datenpaket verarbeitet wird:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
// Es ist ein Datenpaket eingetroffen, untersuchen
procedure TfrmMain.UdpSockUtil1Receive(Sender: TObject);
  var
    SenderIP: in_addr;
    SenderPort: Integer;
    SenderData: AnsiString;
begin
  SenderData := UdpSockUtil1.ReceiveText(SenderIP, SenderPort); // Daten lesen
  if (SenderData = MY_APP_REQUEST) then begin
    // Anfrage nach laufender Instanz
    UdpSockUtil1.RemoteAddr := SenderIP; // an den Absender
    UdpSockUtil1.SendText(MY_APP_REPLY); // die Antwort senden
  end
  else if (SenderData = MY_APP_REPLY) then begin
    // Antwort auf Anfrage nach laufender Instanz
    SenderData := inet_ntoa(SenderIP); // IPddn -> String;
    if ListBox1.Items.IndexOf(SenderData) = -1 then // schon bekannt?
      ListBox1.Items.Add(SenderData); // nein, einfügen
  end
  else
    ShowMessage('Unbekanntes Datenpaket von '+inet_ntoa(SenderIP)+':'+IntToStr(SenderPort));
end;
Hier sind drei Fälle zu unterscheiden:
  1. Es wurde ein Anfrage-Paket empfangen (MY_APP_REQUEST)
    Eine andere Programminstanz (oder ggfs. auch die eigene, Broadcasts werden auch an sich selbst gesendet) fragt nach anderen im LAN. Antwortpaket (nur) an den Absender schicken, damit dieser diese Instanz erkennt.

  2. Es wurde ein Antwort-Paket empfangen (MY_APP_REPLY)
    Vorausgesetzt, wir hatten aus dieser Instanz angefragt, hat eine andere Instanz geantwortet. Absender registrieren :arrow: andere Instanz gefunden (ggfs. müsste man hier noch die eigene Instanz filtern, Ansatz: jede Instanz bei Programmstart eine GUID bilden lassen und diese mitsenden).

  3. Es wurde ein Datenpaket mit einem unbekannten Inhalt empfangen
    Fehler melden und ignorieren.
In Anhang befindet sich das komplette Demo-Projekt.

Hinweis: Da eine statische Service-Port-Zuordnung gemacht wird, kann man das Programm jeweils nur einmal pro Maschine starten. Für einen Test im LAN sind also mehrere PCs (oder VMs) nötig!


FindLanInstance.zip  (1.76 KB) Download (Rev 0)
 (515x, 515x gesamt)
Beschreibung: Demo-Projekt (setzt den installierten TUdpSockUtil voraus), erstellt mit D7(pro)
FindLanInstance.exe  (155 KB) Download (Rev 0)
 (530x, 530x gesamt)
Beschreibung: Fertige Anwendung zum direkten Ausprobieren (Achtung: UPX-gepackt, ggfs. selbst kompilieren, wenn Viruswarnung kommt)
_________________
There are 10 types of people - those who understand binary and those who don´t.