Forum: PC-Programmierung sockets in python und mehrere receiver auf den selben Port


von Miu M. (miumiu)


Lesenswert?

Hi
ich schreibe gerade ein Python programm was auf Port 0x1936 hört. Das 
wird auch von anderen PC Anwendungen benutzt.

Die anderen PC Anwendungen gehen dann nicht oder bringen eine Error 
Meldung: "cannot attach to network"
Das sind meine Python Snippets:

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # UDP
sock.bind(("", self.UDP_PORT))
while not self.stop_receiver:
    data, address = sock.recvfrom(2000)  # buffer size is 1024 bytes
    process(data)

von zonk (Gast)


Lesenswert?

Du kannst einen Socket nur einmal aufmachen, von einem Prozess.

von Rolf M. (rmagnus)


Lesenswert?

zonk schrieb:
> Du kannst einen Socket nur einmal aufmachen, von einem Prozess.

Genauer gesagt: Die Kombination aus IP-Adresse und Port kann nicht 
mehrmals gleichzeitig verwendet werden. Ist die schon von einem Prozess 
belegt, kann ein zweiter sie nicht mehr nutzen.

von 🐧 DPA 🐧 (Gast)


Lesenswert?

zonk schrieb:
> Du kannst einen Socket nur einmal aufmachen, von einem Prozess.

Geht schon: SO_REUSEPORT
https://man7.org/linux/man-pages/man7/socket.7.html#:~:text=Permits%20multiple%20AF_INET%20or%20AF_INET6%20sockets%20to%20be%20bound%20to

Wird aber dem TO nicht weiterhelfen, es dupliziert die Pakete nicht, 
sondern verteilt sie. Ursprünglich wurde es eingeführt, um das 
unterbruchsfreie neu starten von Serveranwendungen zu ermöglichen.

von stg (Gast)


Lesenswert?

In so Fällen kann man
Wenn ein Client sich verbindet, eine freie Socketnummer dem Client 
senden und dort wieder einen Listener einrichten. Danach muss sich der 
Client auf die neue Socketnummer verbinden. Danach den ürsprünglichen 
Socket zurücksetzen und auf einen neue Client warten.

von Imonbln (Gast)


Lesenswert?

Miu M. schrieb:
> ich schreibe gerade ein Python programm was auf Port 0x1936 hört. Das
> wird auch von anderen PC Anwendungen benutzt.

Quad Definition, kann die Kombination IP-Adresse / Port nur von einem 
Programm verwendet werden, entweder von deinem Python oder dem anderen 
Programm. Alles andere zu versuchen ist Murks.
Wenn zwei unterschiedliche Programme die gleiche Kombination IP-Adresse 
/ Port verwenden sollen, brauchst du eine 3 Komponente, welche denn 
Datenverkehr annimmt und als eine Art Proxy/Dispatcher/man in the 
middle/ Router, nach irgendwelchen Kriterien denn Datenstrom an das 
entsprechende Programm weiterleitet. Das wird hässlich, immer! Von daher 
würde ich, wenn das geht, diesen weg vermeiden wollen.

stg schrieb:
> In so Fällen kann man
> Wenn ein Client sich verbindet, eine freie Socketnummer dem Client
> senden und dort wieder einen Listener einrichten. Danach muss sich der
> Client auf die neue Socketnummer verbinden. Danach den ürsprünglichen
> Socket zurücksetzen und auf einen neue Client warten.

Der TO will UDP sprechen, das ist stateless. Von daher ist eine Lösung 
etwas überdimensioniert, zumal er einfach beide Programme auf 
unterschiedliche (feste) Ports binden soll und sein Problem löst sich in 
Wohlgefallen auf.

Abgesehen davon ist ein Vorschlag mit dem dynamischen Bereitstellen 
neuer Server (Instanzen) auf random Ports, ein echter Alptraum für 
Admins. Es mag vielleicht aus Entwickler Sicht eine gute Idee sein, aber 
wenn du, die Infrastruktur dafür betreiben musst und vielleicht noch 
eine Coperate Security Policy mit Firewalls entforcen darfst, kotzt du 
im Strahl, wenn der Entwickler vorschlagt, das Programm macht random 
neue Ports auf.

Irgendwie muss dein Programm dann der einen oder anderen Firewall 
Instanz mitteilen das dieser Port nun aufgehen muss, für eingehenden 
Traffic und vermutlich braucht es auch e1-2 Runden bis IDS, Alterting 
und Monitorring auf diese Albtraum angepasst sind.
Alternativ muss der Admin ganze Port Ranges freigeben, was mit 
Sicherheit zu einer Diskussion mit dem Prüfer der Coperate Security 
Policy, führen wird zum Thema "Securitybreach - offene ungebundene 
ausgehende Ports".

Als Admin würde ich dir also sagen, höchstens mit Event Messaging 
Subsystem das mir rechtzeitig denn neuen Port an und abmeldet und auch 
dann nur äußerst widerwillig wenn es kein Plan B gibt.

von stg (Gast)


Lesenswert?

@Imonbln

Vielen Dank für die Informationen.
Meine Einschätzung ist, der TO will in einem LAN Systeme verbinden.
Zufällig Ports zu testen wäre doof, man kann ja z.B. ab 22567 zu suchen 
anfangen. Dann hätten es Admins auch nicht so schwer ;-)
Vielleicht wäre er mit TCP Sockets besser bedient.

Grüsse

von stg (Gast)


Lesenswert?

Hi

Ein Webserver macht doch etwa was der TO sucht.
Such nach Beispielcode...

von Imonbln (Gast)


Lesenswert?

stg schrieb:
> Ein Webserver macht doch etwa was der TO sucht.
> Such nach Beispielcode...

Ein UPD Proxy in Python ist schnell geschrieben.
1
import socketserver
2
3
class UDPProxy(socketserver.BaseRequestHandler):
4
5
    def setup(self):
6
        ''' 
7
        parse Configuration File here to know everythink about the Backends
8
        '''
9
        pass
10
11
    def handle(self):
12
        data = self.request[0].strip()
13
        socket = self.request[1]
14
        # Insertt logic to deside on which Backend the request should go
15
        # and maybe also a Statemachine for the anwser is needed here
16
17
        # forward data to "backend" with
18
        # socket.sendto(data, <Backend addr>)
19
20
21
if __name__ == "__main__":
22
    HOST, PORT = "localhost", 0x1936
23
    with socketserver.UDPServer((HOST, PORT), UDPProxy) as proxy:
24
        proxy.serve_forever()

Die Logik für das Weiterleiten und die Statemaschine welche man ggf. 
braucht um die Antwort an den Originalsender zu schicken ist, ist 
hässlich zu implementieren und hier hilft dir ein Webserver nicht 
unbedingt weiter da UPD im Vergleich zu TCP Stateless ist. Der Webserver 
muss sich nur den Socket vom Client und dem Backend merken, der UPD 
Proxy kann das nicht.

Abgesehen davon glaube ich immer noch das eigentliche Problem des TO 
ist, das zwei Programme gleichzeitig auf dieselbe Kombination von 
Protokoll, IP, Port hören sollen, und das geht schlicht nicht. Sobald er 
das eingesehen hat und eins seiner Programme auf einen anderen Port 
legt, hat er das Problem nicht mehr, das du mit einem Proxy versuchst zu 
lösen. ;)

von Rolf M. (rmagnus)


Lesenswert?

Imonbln schrieb:
> Abgesehen davon glaube ich immer noch das eigentliche Problem des TO
> ist, das zwei Programme gleichzeitig auf dieselbe Kombination von
> Protokoll, IP, Port hören sollen, und das geht schlicht nicht. Sobald er
> das eingesehen hat und eins seiner Programme auf einen anderen Port
> legt, hat er das Problem nicht mehr, das du mit einem Proxy versuchst zu
> lösen. ;)

Dafür hat er dan das Problem, dass er den Absender dazu überreden muss, 
alle Daten zweimal zu senden (mit unterschiedlichen Ports), damit die 
Empfänger beide die Daten bekommen.

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Rolf M. schrieb:
> Dafür hat er dan das Problem, dass er den Absender dazu überreden muss,
> alle Daten zweimal zu senden (mit unterschiedlichen Ports), damit die
> Empfänger beide die Daten bekommen.

Das könnte man mit iptables lösen. Eine rule für wenn udp source ip, 
dest ip und port einen gewissen Wert haben, lokal an anderen Port 
weiterleiten. Für beide source IPs je eine rule, um das an den jeweils 
richtigen Port der richtigen Anwendung zu senden.

von Rolf M. (rmagnus)


Lesenswert?

🐧 DPA 🐧 schrieb:
> Für beide source IPs je eine rule, um das an den jeweils
> richtigen Port der richtigen Anwendung zu senden.

"beide"? Gibt es denn zwei Source IPs?

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Rolf M. schrieb:
> 🐧 DPA 🐧 schrieb:
>> Für beide source IPs je eine rule, um das an den jeweils
>> richtigen Port der richtigen Anwendung zu senden.
>
> "beide"? Gibt es denn zwei Source IPs?

Falls es 2 PCs gibt, die unterschiedliche Services auf dem selben PC per 
UDP auf dem selben Port ansprechen wollen, dann werden diese je eine IP 
haben. Damit gibt es dann je nach PC eine andere Source IPs.
Das es 2 Client PCs gibt ist zwar auch nur Spekulation.

von Rolf M. (rmagnus)


Lesenswert?

Ah, ich glaube, wir gehen da von unterschiedlichen Annahmen aus. Ich war 
davon ausgegangen, dass irgendwer per UDP etwas an den Rechner sendet 
und er diese Daten nun einfach mit zwei Programmen parallel empfangen 
will.
Leider hat er nicht dazugeschrieben, warum die beiden Programme den 
selben Port nutzen müssen.

von Sheeva P. (sheevaplug)


Lesenswert?

Rolf M. schrieb:
> Ah, ich glaube, wir gehen da von unterschiedlichen Annahmen aus. Ich war
> davon ausgegangen, dass irgendwer per UDP etwas an den Rechner sendet
> und er diese Daten nun einfach mit zwei Programmen parallel empfangen
> will.
> Leider hat er nicht dazugeschrieben, warum die beiden Programme den
> selben Port nutzen müssen.

Für solche Probleme gibt es fertige Lösungen. Man nennt sie Message 
Broker. Gibt es als Standalone-Software (think MQTT) und integriert in 
andere Software wie Redis.

UDP benutzen die meisten übrigens nur, weil ihnen TCP zu kompliziert 
ist. Am Ende fallen sie mit UDP dann leider gerne auf die Nase, wenn 
sich die Anforderungen so ändern, daß sie mit UDP nicht mehr abgebildet 
werden können.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.