Autor Beitrag
Kasko
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 118

Win 10
C# C++ (VS 2017/19), (Java, PHP)
BeitragVerfasst: Fr 06.11.20 02:52 
Ich arbeite an einem Projekt, in dem ich meinen Computer mit meinem Android-Handy steuern kann, das eine Verbindung zu einer Windows-Anwendung herstellt. Es hat also drei Hauptbestandteile:

  1. UDP Broadcast zum Erkennen aller Win-Apps im lokalen Netzwerk.
  2. TCP-Verbindung zum Senden von Befehlen von der Android-App zur Windows App
  3. Sitzungen zum Speichern von Geräten und zum Wiederherstellen von Verbindungen, nachdem die Android-App oder Windows App geschlossen wurde


Ich speichere auf meiner App alle Geräte mit denen ich eine gültige Verbindung habe, ob sie nun aktiv ist oder nicht. Es ist immer nur eine aktive Verbindung erlaubt. Alle anderen werden gespeichert aber beendet un können erneut aufgebaut werden, wenn ich mich mit einem der anderen Geräte verbinden möchte.

So sieht meine Tabelle dafür aus:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
using System.Net;

using SQLite;

namespace WRMC.API.DB {
    [Table("server")]
    public class Server {
        [Column("device")]
        [NotNull]
        public string DeviceDisplayName { get; set; }

        [Column("ip")]
        [NotNull]
        public IPAddress IPAddress { get; set; }

        [Column("session")]
        [NotNull]
        public long SessionID { get; set; }
    }
}


Nun gibt es ein Problem:

  1. Wenn ich die App mit einem Computer in LAN A und einem anderen Computer in LAN B verbinde, besteht eine geringe Wahrscheinlichkeit, dass die lokalen IP-Adressen der Computer gleich sind (z. B. beide 192.168.178.31). Dies führt zu zwei gültigen Sitzungs-IDs für eine IP. Natürlich akzeptiert der Computer aus LAN A nicht beide Sitzungs-IDs, aber es scheint so, würde man sich die Tabelle ansehen. Wenn man beim Aufbau der Verbindung nicht jede vorhandene Sitzungs-ID ausprobieren, führt dies zu einem Verbindungsproblem. Es muss einen besseren Weg geben, wie einen Netzwerk Identifier hinzuzufügen. Ist das möglich?
  2. Wenn ich mein Handy mit einem Laptop in LAN A verbinden, die Verbindung wieder schließe und beide zu LAN B bringe, ändern sich die lokalen IP-Adressen. Sie können also erst dann eine Verbindung herstellen, wenn sie ihre neuen IPs kennen und eine neue Sitzung erstellt wurde. Jedoch kann man auch versuchen einfach einen Broadcast mit der Sitzungs-ID zu senden und das Gerät, welches diese ID kennt, ist das gesuchte. Hier ist also keine Nutzerauswahl erforderlich. Es kann jedoch vorkommen, dass zwei Computer diese Sitzungs-ID als gültige haben. Es gibt auch einen sehr, sehr seltenen Fall, in dem Sie sich in LAN B befinden und ein anderer Computer dieselbe IP und Ihre Sitzungs-ID als gültige ID hat. Dies führt zu einer Verbindung mit dem falschen Computer.


Gibt es Lösungen für diese Probleme?

P.S.: Ich habe diese Frage bereits auf einem anderem Forum gestellt. Jedoch wurde sie dort überhaupt nicht verstanden. Ich habe daher ein Video aufgenommen in dem ich es nochmal deutlicher erkläre. Ich hoffe dies ist erlaubt und ich würde mich freuen wenn sich einige die Zeit nehmen würden dieses Video anzuschauen:

der-magere-student.c...g-LAN-IP-Inhalte.mp4
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18989
Erhaltene Danke: 1685

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 06.11.20 09:35 
Wie wäre es denn mit einer ID für den Server, die dieser immer behält (sprich lokal abspeichert)? Wenn du diese zum Beispiel aus der lokalen Mac und der aktuellen genauen Uhrzeit usw. bildest, ginge die Wahrscheinlichkeit für eine Dopplung gegen Null.

Dann könntest du jederzeit erkennen welche deiner Sessions zu dem aktuell unter der IP gefundenen Server passt (indem du diesen nach seiner ID fragst) und die andere als offline anzeigen.
Kasko Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 118

Win 10
C# C++ (VS 2017/19), (Java, PHP)
BeitragVerfasst: Fr 06.11.20 15:58 
Theoretisch möglich jedoch gibt es dabei zwei Probleme:

  1. Ich kann nicht vor dem Verbindungsaufbau Netwerke ausschließen. Ich muss also immer noch, wenn ich zwei gleiche IPs mit unterschiedlichen Session-IDs habe, beide ausprobieren. Jedoch hat der Server die Möglichkeit direkt Verbindungen abzulehnen aufgrund der erwarteten Server ID. Es löst also nur die Hälfte der Probleme.
  2. Die mag es nicht mit an 0 grenzender Wahrscheinlichkeit zu arbeiten. Sie ist halt fast 0 aber eben nicht 0. Auch mein 2. genanntes Problem hat eine unglaublich geringe Wahrscheinlichkeit von 1:2^160. Trotzdem fühlt sich ein solches Vorgehen für mich nicht sauber an ;)

Nochmal zum ersten: Angestrebt ist es, BEVOR ich einen erneuten Verbindungsaufbau versuche, alle bis auf ein IP-Session-Tuple auszuschließen. Ob der Server eine gewisse ID hat weiß ich erst nachdem ich den Verbindungsaufbau durchgeführt habe.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18989
Erhaltene Danke: 1685

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 06.11.20 16:26 
Da du (außer per W-LAN und der SSID des W-LANs und hier wären ja auch mehrere SSIDs für das selbe Netzwerk denkbar) nicht wissen kannst um welches Netzwerk es sich handelt, kannst du ohne Kontakt zum Server gar nicht wissen, welcher Eintrag aktuell gültig ist. Das geht rein logisch nicht. Denn du hast ja kein Kriterium, an dem du festmachen kannst in welchem Netzwerk du bist, wenn die IP-Range und ggf. auch der Standard-Gateway gleich sind.

Du musst den Server nicht aktiv fragen, wenn er seine ID per UDP herumschickt.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10153
Erhaltene Danke: 1242

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Sa 07.11.20 01:36 
Moin!

user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe daher ein Video aufgenommen in dem ich es nochmal deutlicher erkläre.
Mein Gott, du musst ja wirklich verweifelt sein, wenn du ein 12 Minuten Video für so eine simple Frage aufnimmst. :shock:

user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
Ich hoffe dies ist erlaubt und ich würde mich freuen wenn sich einige die Zeit nehmen würden dieses Video anzuschauen:
Warum sollte es nicht erlaubt sein, aber realistischerweise solltest du nicht davon ausgehen, dass es sich viele Leute (bis zum Ende) ansehen... :?

Kurz gesagt, du hast den Aufbau und die Funktionsweise von Netzwerken evtl. noch nicht gut genug verstanden. Du gehst von der (falschen) Annahme aus, dass es so etwas wie einen "Netzwerkidentifier" überhaupt gibt. Das ist nicht der Fall, es gibt auf dem Layer 3 keine solche "Information". Windows versucht mit einer Reihe von Mitteln so eine Information zu erraten, aber das ist weit davon weg, sauber zu funktionieren (in den meisten "Heim-Netzen" tut es das, deshalb kriegt man das als "Heim-Anwender" nicht so richtig mit und könnte auf den Gedanken kommen, sowas sei Standard). ;)

Wenn der IP-Stack auf deinem Handy (und genauso auf dem Windows-System, auf dem dein Server läuft) "aufwacht" (eine Netzwerkverbindung erkennt), dann weiß dieses Gerät genau gar nichts von seiner "Umgebung". Du gehst beispielsweise von der (ebenfalls falschen) Annahme aus, dass das Windows, auf dem der Server läuft, immer die gleiche (von mir aus auch private) IP-Adresse hat (v4 und v6 kommen da auch noch mit zu). Dem ist nicht so, es sei denn, du hast eine statische IP-Adresse vergeben. Dann wirst du aber in einem anderen, als deinem "Heim-Netz", erhebliche Probleme bekommen. :zwinker:

Da fängt es also schon an: auch der Server kann eine andere IP-Adresse haben als die, die er bei der letzten Verbindung hatte! Zumindest musst du davon ausgehen, denn das kann ausserhalb deines Einflussbereichs liegen. :idea:

Daraus folgt: die IP-Adresse ist kein geeignetes Mittel, um einen Server "wiederzuerkennen"! :mahn:

Lösung: jeder Server braucht eine eigene, eindeutige ID (das hat user profile iconjaenicke ja schon erwähnt). Du könntest beispielsweise beim ersten Start der Server-Anwendung die MAC-Adresse der Schnittstelle nehmen, an die du bindest und die Systemzeit, daraus einen Hash (MD5, SHA, such dir was aus) bilden und diesen als Server-ID abspeichern. Die Wahrscheinlichkeit, dass dieser Wert weltweit kollidiert, dürfte nicht mehr als realistisch gelten (aber da du so drauf rumreitest: ja, theoretisch könnte dieser Hash mehrmals auftreten, die Verfahren sind ja nicht kollisionsfrei; wenn du allerdings hier ernsthaft jegliche potenzielle Kollision ausschließen willst, dann gibt das Projekt lieber auf, das lohnt dann nicht mehr :nut:).

Wie grade schon ausgeführt, auch deine Android-App hat das gleiche Problem, nach dem Eintritt in ein Netz ist genau gar nix bekannt, auch keine Server und schon gar nicht deren IP. Es bleibt dir also nichts anderes übrig, als mit einem UDP-Broadcast nach laufenden Server-Instanzen zu suchen (warum soll das übrigens so wenig wie möglich passieren? gibt es irgendeinen nachvollziehbaren Grund dafür? praktisch alle gängigen Betriebssysteme labern dauernd auf dem Netz rum, glücklicherweise per UPD, genau deshalb wird das idR ja auch nicht geroutet). :nixweiss: In der Antwort auf den initialen "Welche Server laufen im Netz?"-Broadcast liefert der Server dann seine ID ab (oder ggfs. auch mehrere), und schon kannst du in deiner DB nach einer passenden Session-ID suchen. Hast du keine Session, kannst du dem Benutzer die gefundenen Server präsentieren und einen raussuchen lassen.
So wird ein Schuh draus. :think:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.

Für diesen Beitrag haben gedankt: icho2099
Kasko Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 118

Win 10
C# C++ (VS 2017/19), (Java, PHP)
BeitragVerfasst: So 08.11.20 20:07 
Ich glaube ich wurde an einigen Stellen missverstanden. Mir ist bewusst, dass sowohl Client als auch Server initial nichts über die Umgebung wissen. Deshalb basieren die Probleme ja auch darauf, dass der Client beim Versuch eine Verbindung wieder aufzubauen die Anfrage ins Blaue hinein schickt, nämlich an die ServerIp der zuletzt gespeicherten Verbindung.

Zitat:
Du gehst beispielsweise von der (ebenfalls falschen) Annahme aus, dass das Windows, auf dem der Server läuft, immer die gleiche (von mir aus auch private) IP-Adresse hat

Dessen bin ich mir auch bewusst. Problem 2 basiert darauf, in welchem ich auch ein Windows Gerät z.B. einen Laptop, der als Server fungiert hat, in ein anderes Netzwerk 'bringe'.

Zitat:
Dann wirst du aber in einem anderen, als deinem "Heim-Netz", erhebliche Probleme bekommen. :zwinker:

Genau darum geht es ja in beiden genannten Problemen :zwinker:

Zitat:
warum soll das übrigens so wenig wie möglich passieren? gibt es irgendeinen nachvollziehbaren Grund dafür? praktisch alle gängigen Betriebssysteme labern dauernd auf dem Netz rum, glücklicherweise per UPD, genau deshalb wird das idR ja auch nicht geroutet
Ich möchte nicht, dass so wenig wie möglich UDP-Pakete versendet werden.

Zitat:
kannst du dem Benutzer die gefundenen Server präsentieren und einen raussuchen lassen.

Das soll so wenig wie möglich passieren, damit man den Nutzer nicht zur Weißglut bringt. :zwinker:


Zitat:
dann gibt das Projekt lieber auf, das lohnt dann nicht mehr :nut:

Geht nicht und will ich nicht. Ist sowohl für private Nutzung als auch ein Uniprojekt.

Zitat:
jeder Server braucht eine eigene, eindeutige ID

Ich habe jetzt jedem Server und jedem Client eine ID gegeben, bestehend aus:

  1. MachineName
  2. MAC-Adresse
  3. OS-SerienNummer
  4. Prozessor-Id
  5. Mainboard-Seriennummer


Mag für euch vielleicht etwas übertrieben wirken, aber ich kenne mein Glück und wahrschein würde sonst genau, wenn ich das Projekt vorstelle und mein Prof es ausprobiert so ein Duplicat auftreten und alles kaputt machen :zwinker:

P.S.
Zitat:
Mein Gott, du musst ja wirklich verweifelt sein, wenn du ein 12 Minuten Video für so eine simple Frage aufnimmst. :shock:

Wenn es eine so einfache Frage ist, wieso ist das andere Forum, dann schon beim verstehen so kläglich gescheitert wie an einer Mathe-Klausur :P
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18989
Erhaltene Danke: 1685

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 08.11.20 22:18 
user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
  1. MachineName
  2. MAC-Adresse
  3. OS-SerienNummer
  4. Prozessor-Id
  5. Mainboard-Seriennummer


Mag für euch vielleicht etwas übertrieben wirken, aber ich kenne mein Glück und wahrschein würde sonst genau, wenn ich das Projekt vorstelle und mein Prof es ausprobiert so ein Duplicat auftreten und alles kaputt machen :zwinker:
Diese Informationen sind nicht immer gefüllt in den Systeminformationen (und ohne Adminrechte auch nicht unbedingt auslesbar). Von daher ist eine Kollision hier wahrscheinlicher als mit IP + Datum und Uhrzeit, weil dann eine Kollision nur passieren kann, wenn die IP-Adresse und die Startzeit und ggf. weitere Kriterien bis auf einen Bruchteil einer Sekunde identisch sind.

Aber eine Kollision ist so oder so unwahrscheinlich, von daher: Hauptsache es funktioniert.

Für diesen Beitrag haben gedankt: Narses
Kasko Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 118

Win 10
C# C++ (VS 2017/19), (Java, PHP)
BeitragVerfasst: So 08.11.20 22:39 
Dann füge ich 6. Installations-DateTime hinzu :wink:
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10153
Erhaltene Danke: 1242

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 09.11.20 00:23 
Moin!

user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
Ich glaube ich wurde an einigen Stellen missverstanden.
Ich gehe inzwischen davon aus, dass du dich in dieser Rolle durchaus zuhause fühlst. Aber das ist deine Sache und mindestens OT. :nixweiss:


user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
Mir ist bewusst, dass sowohl Client als auch Server initial nichts über die Umgebung wissen.
Du hörst mir nicht zu oder willst mich nicht verstehen, deshalb ein letzter Versuch: sowohl Client als auch Server sind nach jeder Unterbrechung einer aktiven Netzwerkverbindung immer wieder in dieser Situation. Toggelt der NIC-Link, ist alles, was du glaubtest über das Netz zu wissen, Schall und Rauch. Jedes mal. Deshalb bleibt dir für eine stabile Funktionsweise nichts anderes übrig, als nach einem Netzwerkwechsel wieder alle Server neu zu suchen. Übrigens...
user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
ich kenne mein Glück und wahrschein würde sonst genau, wenn ich das Projekt vorstelle und mein Prof es ausprobiert [...] alles kaputt machen
Genau darauf zielt dieser Hinweis ab. ;)

user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
Ich möchte nicht, dass so wenig wie möglich UDP-Pakete versendet werden.
Gehen wir mal von einem "nicht" zuviel aus, das müssen wir für die Wertung wieder abziehen. :zwinker: Das ist löblich und sinnvoll, scheitert aber an dem "wie möglich". :nixweiss: Es ist eben nicht möglich eine Server-Instanz nach einem Netzwerkwechsel sicher wiederzufinden, ausser du fragst selbige Dienste im Netz ab. :idea:

user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
dass der Client beim Versuch eine Verbindung wieder aufzubauen die Anfrage ins Blaue hinein schickt, nämlich an die ServerIp der zuletzt gespeicherten Verbindung.
Und diese nutzlosen Daten sind egal (sofern der Server nicht erreichbar ist)? Noch dazu wird so ein Versuch per TCP erstens erheblich viel mehr Datenpakete produzieren und zweitens sehr viel länger dauern, da das TCP-Timeout abgewartet wird. Also für mich klingt es sehr viel sinnvoller, wenn erstmal getestet wird, ob ein Verbindungversuch überhaupt eine Chance hat. :idea:

user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
Zitat:
kannst du dem Benutzer die gefundenen Server präsentieren und einen raussuchen lassen.
Das soll so wenig wie möglich passieren, damit man den Nutzer nicht zur Weißglut bringt.
Du hast meine Herleitung nicht genau genug gelesen oder nicht verstanden, deshalb noch ein Versuch: niemand und insbesondere ich habe nicht gesagt, dass du das jedes mal tun sollst. :zwinker:
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
In der Antwort auf den initialen "Welche Server laufen im Netz?"-Broadcast liefert der Server dann seine ID ab (oder ggfs. auch mehrere), und schon kannst du in deiner DB nach einer passenden Session-ID suchen. Hast du keine Session, kannst du dem Benutzer die gefundenen Server präsentieren und einen raussuchen lassen.

Mich würdest du übrigens, rein theoretisch gesprochen, sehr schnell zur Weißglut bringen, wenn du mir ein TCP-Timeout aufzwingst, nur weil sich irgendeine IP-Adresse geändert hat und der Verbindungsaufbau, der gar nicht klappen kann, "ewig" braucht, bis die SW merkt, dass es gar nicht klappen kann... 8)

user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe jetzt jedem Server und jedem Client eine ID gegeben, bestehend aus:
[...]
Mag für euch vielleicht etwas übertrieben wirken
Langsam beschleicht mich der Verdacht, dass du mir gar nicht folgen willst oder kannst. :suspect: Du kannst auch einen Hash aus dem Gesamtinhalt der Platte machen und hast das Problem der Kollisionen nicht (theoretisch) gelöst, es kann immer noch eine Kollision auftreten (bei "deinem Glück" insbesondere :lol:). Die Frage ist, wie wahrscheinlich ist das. Du löst das Problem der möglichen Kollision nicht durch mehr Eingangsdaten. :mahn:

Du hast das Problem in der Realität gelöst, wenn du die MAC-Adresse und die Uhrzeit/Systemzeit/Ticks in einen (halbwegs modernen) Hash umwandelst. Du wirst das Problem in der Theorie nie lösen können.

Es gäbe noch den Ansatz mit einer zentralen Registrar-Instanz im Internet, die solche IDs vergibt, aber das wolltest du glaube ich nicht machen.

user profile iconKasko hat folgendes geschrieben Zum zitierten Posting springen:
P.S.
Zitat:
Mein Gott, du musst ja wirklich verweifelt sein, wenn du ein 12 Minuten Video für so eine simple Frage aufnimmst. :shock:

Wenn es eine so einfache Frage ist, wieso ist das andere Forum, dann schon beim verstehen so kläglich gescheitert wie an einer Mathe-Klausur
Das wird dein Geheimnis bleiben, da du uns nicht erleuchten möchtest, wo das passiert ist (und nein, ich will es auch eigentlich nicht wissen :P). Ganz persönlich fand ich die Lineare Algebra und Analysis-Vorlesungen damals aber auch erheblich viel leichter, als Netzwerktechnik heute. :zustimm:

Und noch ein Disclaimer, da du im Betriebsmodus "keiner versteht mich" vermutlich der Meinung sein wirst, dass ich hier unbedingt "Recht haben will". Dem ist nicht so, ganz ehrlich, was hätte ich davon. Du kannst und wirst eh tun, was du willst, und niemand ausser der Realität werden und wollen dich davon überzeugen, ob das so gut und richtig ist. Du hast eine Frage gestellt, ich habe versucht, eine möglichst verständliche Antwort zu geben, das ist schon alles.

Viel Erfolg noch! :wave:
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.

Für diesen Beitrag haben gedankt: icho2099