Zum Inhalt springen

Mehrere UDP-Sockets auf gleichen Port hören lassen


speedi

Empfohlene Beiträge

Hallo,

ein Programm schreiben, welches auf einen Datagram-Socket lauscht und die Daten visualisiert. Das Programm soll mehrfach geöffnet werden können (Kundenanforderung).

Eigentlich dachte ich mir: ok, dann setze ich den Socket

setReuseAdress(true)
und fertig. Leider bekomme ich dennoch BindException (Adress already in use). Ein Kollege meinte man müsse erst setReuse(true) machen und dann binden - im nachhinein ginge da nicht. Ok... das wollte ich nun ausprobieren und da sagt mir der socket schon gebunden ist.
      DatagramSocket mSocket = new DatagramSocket();

      mSocket.setReuseAddress(true);

      mSocket.bind(new InetSocketAddress(mPort));

Hab auch schon versucht mit disconnect vor dem bind => hilft nichts.

Link zu diesem Kommentar
Auf anderen Seiten teilen

      DatagramSocket mSocket = new DatagramSocket(null);

      mSocket.setReuseAddress(true);

      mSocket.bind(new InetSocketAddress(mPort));

Ok... wenn ich den Socket mit null instanziere gehts schonmal bisschen weiter. Leider bekommt der zweite Prozess jetzt keine Daten. Der erste frisst alles weg.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi,

also ich bin nicht sicher ob ich dich richtig verstanden habe, aber ich glaube nicht dass das geht. So wie ich setReuseAddress verstehe, geht es einfach darum, die TIME_WAIT Zeit "abzuschalten", d.h. wenn die Verbindung geschlossen wird, sofort eine neue Verbindung aufgebaut werden kann.

Dass du mehrere Programm öffnest du die den gleichen Port mit der selben IP nutzen, kann nicht funktionieren. Ein Apache löst sowas beispielsweise über Threads, vielleicht meint dein Kunde soetwas?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Der Kunde will, dass die Software mehrfach lauft und die Daten welche über einen bestimmten UDP-Port reinkommen in jeder Instanz angezeigt werden. Wenn das nicht möglich ist die Daten in mehreren Prozessen gleich zu lesen, müsste ich quasi einen Master-Receiver schreiben, der die Daten dann z.B. über einen TCP-Server an die einzelnen Prozesse verteilt. Ich hatte gehofft mir das sparen zu können.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Bitte einfach mal Google verwenden zu diesem Thema gibt es schon eine Menge an Informationen mit Beispielen. Zusätzlich als Hinweis, man bindet an ein Interface / Adresse und Port, ein Port alleine ist nicht ausreichend

Danke dir. Gegoogelt habe ich schon. Das man an ein interface bindet ist mir schon klar. Weißt du, ob das was ich vor habe generell Möglich ist - oder geht das nicht? Hast du vielleicht noch weitere Brotkrumen die mir weiterhelfen könnten?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Rfc 768 ;-)

Sind hier eigentlich alle so hilfreich?

Ich weiß durchaus wie ein UDP-Header ausschaut, aber inwieweit hilft das bei der Lösung des Problems?! Ich implementiere auch nicht zum ersten mal einen UDP-Reader, aber diesmal gibts halt eine neue Anforderung von der ich nicht weiß, ob/wie das möglich ist. Ich hatte eigentlich gehofft irgendwer hätte hier einen entscheidenden Tipp. Aber das war wohl nichts. So funktionieren Foren wirklich super^^

Derzeitiger Status

DatagramSocket mSocket = new DatagramSocket();

mSocket.setReuseAddress(true);

mSocket.bind(new InetSocketAddress(mPort));

Damit lassen sich jetzt beliebig viele Sockets instanzieren, die auch - scheinbar - alle auf den Port lauschen. Leider bekommt nur der Socket der zuerst instanziert wurde Daten. Ich habe auch versucht noch eine IP-Adresse mit anzugeben, aber das nutzt auch nichts - immer nur der erste bekommt etwas.

Bearbeitet von speedi
Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi,

bist du denn sicher, dass die alle auf dem selben Port lauschen? Was sagt denn ein netstat -na oder sowas?

Vielleicht nochmal zum Verständnis: Du möchtest Programm X starten, was auf IP-Adresse 192.168.0.1 und Port 4711 lauscht. Dann startest du das Programm nochmal, und es lauscht auch wieder auf Adresse 192.168.0.1 und Port 4711. Oder wie meinst du das?

Bearbeitet von carstenj
Link zu diesem Kommentar
Auf anderen Seiten teilen

Teil dein Programm doch einfach in ein Lauscherprogramm und ein Visualisierungsprogramm. Das Lauscherprogramm nimmt die Daten entgegen und stellt sie so bereit, dass mehrere Instanzen des Visualisierungsprogramms drauf zugreifen können.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Von wem erhält Dein Programm denn seine Daten? Von unterschiedlichen Quellen oder eben auch nur von einer Quelle? Evtl. wäre der Artikel http://de.wikipedia.org/wiki/Socket_(Software) relevant.

Wenn der Server eine Anfrage von einem Client erhält, wird aus dem lauschenden ("listening") Server-Socket das in Verbindung stehende ("connected") Server-Socket abgeleitet: Der ursprüngliche Server-Socket bleibt erhalten und wartet weiterhin auf neue Verbindungen, während ein neuer, auf den bestimmten Client gerichteter Socket geöffnet wird, der nur für die Kommunikation mit diesem einen Client verwendet wird. Dieser bleibt solange bestehen, bis die Verbindung zum Client von einer der beiden Seiten beendet wird. Dieses Ableiten kann dazu genutzt werden, eine parallelisierte Serverarchitektur zu schaffen, in der sich der Server bei einer Anfrage forkt und ein Kindprozess die Anfrage selbst beantwortet.

Das heißt, dass ein mit einem Client-Socket verbundener ("connected") Server-Socket genau die gleiche IP-Adresse und Port-Nummer trägt wie der lauschende ("listen") Server-Socket. Die Unterscheidung von gleichzeitigen Client-Verbindungen zum selben Server erfolgt daher durch das Paar von Server-Socket und Client-Socket. Dieses Paar muss zu jedem Zeitpunkt eindeutig auf jedem der beteiligten Kommunikationspartner sein. Als Beispiel sei ein HTTP-Server gegeben der auf Port 80 lauscht. Die Verbindungen des Servers zu verschiedenen Clients führt zu folgenden eindeutigen "Connected"-Socket-Paaren auf dem Server-Rechner:

(<Server-IP>:80;<Client_A-IP>:<Client_A_Port_1>), (<Server-IP>:80;<Client_A-IP>:<Client_A_Port_2>), (<Server-IP>:80;<Client_B-IP>:<Client_B_Port_1>) usw. .

So, wie sich Dein Ansatzt anhört, ist Deine Architektur falsch!

Du solltest zwischen dem Subsystem, welche auf's Lauschen getrimmt ist und der Darstellung trennen.

Observer (Entwurfsmuster) <- lautet das Stichwort.

Link zu diesem Kommentar
Auf anderen Seiten teilen

@carstenj:

Zu netstat:

UDP    [::]:1987              *:*

UDP    [::]:1987              *:*

UDP    [::]:1987              *:*

UDP    [::]:1987              *:*

Das erscheint mir eigentlich schon so als würden da 4 Programme auf 1987 lauschen. Ich habe keine Adresse angegeben in dem Fall - also ist egal wo es her kommt. Aber auch wenn ich das tue ist der Effekt der gleiche.

__________________________

@SilentDemise

Mir kommts mittlerweile vor als hättest du recht. Der Projektleiter meinte halt nur es würde gehen und sei Sache des UDP-Stacks im Betriebssystem. Leider ist der zur Zeit nicht da.

__________________________

@afo

Das aufteilen werde ich jetzt wahrscheinlich auch tun. Ich lasse die Daten zentral ankommen und verteile sie dann über einen kleinen TCP-Server.

__________________________

@lilith2k3

Der von dir gepostete Text ist eine Beschreibung zu TCP damit wäre das Problem gar nicht da.

Natürlich trenne ich in der Software GUI und Empfangsteil. Das Observer-Pattern ist mir ein Begriff und findet auch Verwendung.

Die Sache ist im Grunde die: Ich bekomme verschiedene Daten von einem Mobilen System auf einem Port (definierte Messages). Diese sollen auf einen Rechner mit mehreren Bildschirmen in verschiedenen Programmen angezeigt werden. z.B. Ein Programm zur Anzeige der Position auf einer Karte. Ein Programm zur Anzeige von Viodeobildern. Ein Programm zur Anzeige von Statusdaten. Daher braucht natürlich jedes Programm die Daten. Ich hätte das ganze am liebsten in einem Programm gemacht - welches halt einfach mehrere Frames hat. Aber leider ist das so eine Vorgabe gegen die ich mit sachlicher Argumentation nicht ankomme. Es ist nicht direkt die gleiche Software die da paar mal läuft, aber es ist eben der gleiche Receiver der die gleichen Daten braucht.

Bearbeitet von speedi
Link zu diesem Kommentar
Auf anderen Seiten teilen

Die Sache ist im Grunde die: Ich bekomme verschiedene Daten von einem Mobilen System auf einem Port (definierte Messages). Diese sollen auf einen Rechner mit mehreren Bildschirmen in verschiedenen Programmen angezeigt werden.

Und wieso musst Du bei diesem Vorhaben das Programm mehrfach starten?

z.B. Ein Programm zur Anzeige der Position auf einer Karte. Ein Programm zur Anzeige von Viodeobildern. Ein Programm zur Anzeige von Statusdaten. Daher braucht natürlich jedes Programm die Daten. Ich hätte das ganze am liebsten in einem Programm gemacht - welches halt einfach mehrere Frames hat. Aber leider ist das so eine Vorgabe gegen die ich mit sachlicher Argumentation nicht ankomme. Es ist nicht direkt die gleiche Software die da paar mal läuft, aber es ist eben der gleiche Receiver der die gleichen Daten braucht.

Genau das sagen wir Dir !? Ich würde eben eine Komponente machen, die die Daten auf dem UDP Port entgegen nimmt und dann eben eine Komponente die die Darstellung, die hier bei Dir mehrfach sein muss, übernimmt. Das wäre auch vom Design her die richtige Lösung.

So wie es sich anhört, würde man auch kein UDP sondern wohl eher ein Multi- oder Unicast nehmen, denn Du hast hier einen (?) Empfänger, d.h. die Geräte senden an eine Unicast Adresse.

Zu dem Problem, Du kannst den Socket nur einmal erzeugen, d.h. wenn jedes Programm ein new auf den Socket macht, wird es Probleme geben, d.h. bevor Du den Socket erzeugst musst Du prüfen, ob er in Verwendung ist und wenn ja, musst Du nutzen, anstatt zu versuchen ihn neu zu binden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Geht es denn vielleicht noch eine ID oder so mitzugeben, anhand der erkannt werden kann, welche Instanz gemeint ist, so dass nicht die erste Instanz alle Daten erhält und teils damit gar nichts anfangen kann, da sie gar nicht für sie bestimmt waren.

Alternativ könntest du es auch so machen, wie sehr viele andere Anwendungen (beispielsweise der Apache Webserver) das auch machen, dass sie über einen festen Port einen dynamischen Port aushandeln, über den dann die Kommunikation geht. Die Anwendung ist also immer unter sagen wir mal z.B. Port 80 erreichbar und gibt deinem PC dann den entsprechenden dynamischen Port zurück, auf dem Daten erwartet werden.

Sollte ja eigentlich problemlos möglich sein von der Netzwerkseite her.

Wie das jedoch implementiert wird, bin ich leider überfragt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich verfolge jetzt folgende Lösung:

Ich habe einen simplen UDP-Receiver/TCP-Server der bei Start des Rechners gestartet wird. Wenn ein Packet ankommt lege ich das auf einen Stack und der TCP-Server verteilt dann die empfangenen Daten an die Clients (Karte/Videoviewer/StatusView).

@Flashpix: Es handelt sich bei den UDP-Daten um Broadcast-Daten später auch Multicast.

Nochmal:

Die Daten werden Software-Intern nach Oberserver-Pattern verarbeitet. Im Detail bedeutet, dass der jetzige UDP-Receiver (in Zukunft ein TCP-Client) empfängt die Daten und legt sie auf einen Stack. Die Daten auf dem Stack werden dann von einem Thread entspack, in Objekte gewandelt und dem Eventbus übergeben. Wenn eine Komponente nun eine Message empfangen will meldet sie sich am Eventbus an und bekommt ihre Daten um damit zu machen, was immer sie möchte.

Ursprüngliches Problem nochmal genauer erklärt

Stellt euch einfach vor ihr habt einen TV Empfänger (nur ein Kanal!) und Empfangt alle Daten auf einem UDP-Port (Broadcast). Da muss zum einen das Video angezeigt und zum anderen der Videotext (der in die Videodaten anhand der Pixeldaten mit reinkodiert ist). Es ist nun aber gefördert, dass diese zwei Teilkomponenten nicht in einer einzigen Software laufen sondern getrennt (unterschiedliche Prozesse!! "unabhängige ausführbare Jar-Files". Deshalb dachte ich das einfachste wäre, wenn es einen Receiver gibt den sowohl Videotext als auch TV-Anwendung als API verwenden um sich daraus die benötigten Daten zu ziehen.

Ich brauche nicht unbedingt nachhilfe in Software-Architektur - ich wollte lediglich wissen ob/wie es möglich ist das beide die Daten empfangen. Wenn beide auf unterschiedlichen Rechnern laufen geht das ja auch stressfrei. Naja... jetzt hab ich ne Lösung - wenn auch nicht so simpel wie ich es gern gehabt hätte.

In meinem Fall kommt es schon vor das zwei Anwendungen die gleichen Daten brauchen um ihre Ergebisse zu errechnen. Im Detail kann ich darauf aber nicht eingehen.

@Crash:

Die Idee mit den dynamischen Ports ist nett. Da könnte ich einfach anweisen, dass eingehende Messages auf Port 1987 repeatet werden auf localhost:1988 für Map, localhost: 1989 für Video etc... Aber ich denk ein TCP-Server der auf einem festen Port verbindungen entgegen nimmt und lokal läuft erfüllt den gleichen Zweck und jeder Client kann sich an und abmelden ohne dass ich erst irgendwelche Portnummern aushandeln muss.

Danke auf jeden Fall schonmal an alle.

Ich bin mal gespannt, was der PL sagt wenn er wieder da ist - der meinte ja das wäre kein Problem^^

Link zu diesem Kommentar
Auf anderen Seiten teilen

Was ich niemals vor hatte: (weil ich denke dass das einige denken)

Niemals wollte ich das innerhalb einer Software mehrere Komponenten ihren eigenen Socket erzeugen und darauf Daten abgreifen die andere Komponenten auch schon verarbeiten. Sowas wäre in der Tat ziemlicher Blödsinn.

Aber jede eigentständige Software muss natürlich ihre Daten irgendwoher bekommen. Und rein mit Listenern ist mir da einfach nicht geholfen. Damit kann ich ja lediglich Daten verteilen die schon da sind.

Bearbeitet von speedi
Link zu diesem Kommentar
Auf anderen Seiten teilen

Mit UDP Sockets müsste man meines Wissens gleichzeitig von verschiedenen Anwendungen den gleichen Port abgreifen können. Nur muss jede Instanz, d.h. bei Dir jedes Programm, prüfen, ob der Socket existiert und wenn er das tut, sich dran hängen (reuse), andernfalls erzeugt sie ihn.

Was Du da jetzt mit dem TCP vorhast, ist mir nicht klar: Du willst also Videodaten per TCP übertragen? Du solltest bei so etwas bei UDP bleiben.

Ich würde folgendes machen: Eine Instanz hört auf einem Port auf die Daten und packt sie beim Emfang in eine Pipe. D.h. Du hast für jede Anwendung eine Pipe im System. Die Anwendungen, die die Daten darstellen, holen sich die Daten aus der Pipe einfach raus. Dies setzt natürlich voraus, dass nur eine Anwendung aus der Pipe die Daten liest. Der Vorteil ist, dass die Netzwerkkomponente die Daten von einer Seite in die Pipe schiebt, und die Visualisierungskomponente die Daten nur immer liest.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mit UDP Sockets müsste man meines Wissens gleichzeitig von verschiedenen Anwendungen den gleichen Port abgreifen können. Nur muss jede Instanz, d.h. bei Dir jedes Programm, prüfen, ob der Socket existiert und wenn er das tut, sich dran hängen (reuse), andernfalls erzeugt sie ihn.

Das ist im Grunde was ich wollte. Ich bin zwar schon am googlen, aber weißt du vielleicht auf die schnelle wie man sich einen Socket holen kann, den ein anderes Programm bereits erzeugt hat?

Was Du da jetzt mit dem TCP vorhast, ist mir nicht klar: Du willst also Videodaten per TCP übertragen? Du solltest bei so etwas bei UDP bleiben.

Ich dachte ich lasse ein Programm im Hintergrund laufen welches die UDP-Daten liest und dann via TCP auf dem Rechner an die einzelnen Programme verteilt. Pipes gehen ja nur Software-Intern - oder? - deshalb TCP. Dann hängt sich die jeweilige Software an den TCP-Server und bekommt die UDP-Messages über den Stream (message-Length als int und dann die eigentliche message. d.h. ich kanns genau so behandeln wie ich es vorher vor hatte und muss nur minimale Änderungen machen).

Eine Instanz hört auf einem Port auf die Daten und packt sie beim Emfang in eine Pipe. D.h. Du hast für jede Anwendung eine Pipe im System.

Also gehen Pipes doch auch Programm-Übergreifend... ok, ich schaus mir an.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...