P2P Implementierung

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Gromobir
User
Beiträge: 9
Registriert: Donnerstag 14. Oktober 2004, 21:20

Guten Tag,
Nach langer, langer Zeit wollte ich mich wieder ein wenig intensiver mit Python beschäftigen und würde dazu gerne eine kleine P2P Implementation schreiben.
Nachdem ich nun bereits in diesem Forum und im Internet gesucht habe, bin ich unter anderem auf Twisted gestoßen, hege jedoch die Vermutung, dass Twisted für meine Wünsche ein wenig überdimensioniert ist.
Ich möchte:
1.) Das Netzwerk nach lauschenden UDP-Server auf einem bestimmten Port absuchen.
2.) Zu diesen Server verbinden.
3.) Wechselseitig Pakete austauschen um zu versichern, dass die Verbindung über TCP/IP hergestellt werden kann.
Falls ihr mir dazu (gerne auch in Form von Code-Snippets) einige Anregeungen geben könnt, würde ich mich sehr freuen. :)
Es lebe der Informationskommunismus ! :)
Meine Jabber ID : Gromobir@draugr.de
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Ich habe eine ganze Applikation geschrieben die so funktioniert. Bin diese jedoch noch etwas am polieren. Falls du möchtest kann ich dir jedoch schon jetzt eine Kopie des Codes zukommen lassen.

Ansonsten habe ich in den Code Snippets mal geschrieben wie man mit Python UDP Broadcasts macht:
http://www.python-forum.de/topic-11193.html
Gromobir
User
Beiträge: 9
Registriert: Donnerstag 14. Oktober 2004, 21:20

Guten Abend veers,
Ich habe eine ganze Applikation geschrieben die so funktioniert. Bin diese jedoch noch etwas am polieren. Falls du möchtest kann ich dir jedoch schon jetzt eine Kopie des Codes zukommen lassen.
Das wäre sehr nett. Wenn du den Code nicht öffentlich machen möchtest, kannst du mir gerne eine PN schreiben. :)

Dein verlinktes Beispiel geht auf jeden Fall schon einmal in die richtige Richtung. Da ich jedoch mit der Zeit ein P2P-Programm implementieren möchte, müssten der Server und der Client in einem Programm zugleich und nicht getrennt vorliegen.
Sehe ich das richtig, dass

Code: Alles auswählen

sock.sendto(msg, ("255.255.255.255", 6666)) 
an ein ganzes Subnetz verschickt?

//edit: Fehlerteufel exorziert
Es lebe der Informationskommunismus ! :)
Meine Jabber ID : Gromobir@draugr.de
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

TinyP2P ist ein Python-P2P-Programm, dass zugleich auch als *kleines* Beispiel herhalten kann ;)
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Gromobir hat geschrieben: Sehe ich das richtig, dass

Code: Alles auswählen

sock.sendto(msg, ("255.255.255.255", 6666)) 
an ein ganzes Subnetz verschickt?

//edit: Fehlerteufel exorziert
Ja

Code: Alles auswählen

255.255.255.255 ist die allgemeine Broadcast Adresse, ja.

Und dazu das Client/Server getrennt sind, hindert dich nichts daran das zu kombinieren. Es ist aber keine Bedingung für P2P das Client und Server das selbe Programm sind. ;)
Gromobir
User
Beiträge: 9
Registriert: Donnerstag 14. Oktober 2004, 21:20

Guten Abend,
@Y0Gi: tinyp2p kannte ich bereits, fand es jedoch zum Lernen nicht sehr brauchbar, da der Code doch durch einige Kniffe stark komprimiert wurde. ;)

@veers:
Es ist aber keine Bedingung für P2P das Client und Server das selbe Programm sind.
Wenn Server und Client in zwei verschiedene Programme gesplittet sind, erfüllen beide ja unterschiedliche Aufgaben. Bei P2P sollte es jedoch so sein, dass ein Programm sowohl als Server (für den Upload), als auch als Client (für den Download) fungieren kann. Kläre mich aber dennoch bitte auf, falls ich hier einen Denkfehler gemacht habe.

Code: Alles auswählen

#!/usr/bin/python
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #socket.AF_INET == IPv4 socket; socket.SOCK_DGRAM == UDP socket
sock.bind(("", 6666)) # bind to host "" (any) and port 6666
message = "ping"
while True:
  sock.sendto(message, ("127.0.0.1", 6666))
  msg, addr = sock.recvfrom(1024)
  print msg
  sock.sendto(message,addr) 
Obiger Code ist schon mal der zaghafte Versuch des wechselseitigen Pingens. Wenn ich 127.0.0.1 durch 255.255.255.255 ersetze, um einen Socket zu haben, der auf der Broadcasting-Adresse lauscht bzw. gebunden ist, erhalte ich leider immer die folgende Fehlermeldung:

Code: Alles auswählen

socket.error: (13, 'Permission denied')
Desweiteren möchte ich ja später alle Peers im Netzwerk finden, die das Programm benutzen. Wäre hier vielleicht eventuell nicht die Multicast-Methode besser geeignet um die Last ein wenig zu verteilen?
Es lebe der Informationskommunismus ! :)
Meine Jabber ID : Gromobir@draugr.de
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Gromobir hat geschrieben: @veers:
Es ist aber keine Bedingung für P2P das Client und Server das selbe Programm sind.
Wenn Server und Client in zwei verschiedene Programme gesplittet sind, erfüllen beide ja unterschiedliche Aufgaben. Bei P2P sollte es jedoch so sein, dass ein Programm sowohl als Server (für den Upload), als auch als Client (für den Download) fungieren kann. Kläre mich aber dennoch bitte auf, falls ich hier einen Denkfehler gemacht habe.
P2P sagt eigentlich nur das du direkte Verbindungen/Kommunikation zwischen den einzelnen Computern/Peers hast. Die Peers können jeweils Dienste zur Verfügung stellen oder nutzen. Diese müssen nicht im selben Programm/Prozess sein.

Zum "Permission Denied", du musst vermutlich die Broadcast Option setzen.

Zum finden der Peers, ich hatte dieses Problem auch. Der effizienteste weg wäre eine Art "Heartbeat" wo jeder Peers in einem gewissen Interval "Hey mich gibts auch noch" Packete versenden. Wenn Peers einen Heartbeat von einem unbekannten/als offline markierten Peer erhalten wäre es klug sofort mit einem Heartbeat zu Antworten damit der Client diese sofort sieht.

Diese Methode ist jedoch etwas aufwändig, deshalb habe ich derzeit in meinem Lan Filesharing Tool einen einfachen Broadcast drin auf den alle Peers Antworten. Der Overhead ist zumindest bei meiner Anwendung beinahe inexistent.
Gromobir
User
Beiträge: 9
Registriert: Donnerstag 14. Oktober 2004, 21:20

Guten Tag,
Zum "Permission Denied", du musst vermutlich die Broadcast Option setzen.
Das stimmt, danke.

Code: Alles auswählen

sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
behebt diese Fehlermeldung.
Der effizienteste weg wäre eine Art "Heartbeat" wo jeder Peers in einem gewissen Interval "Hey mich gibts auch noch" Packete versenden
Das liest sich nach einer optimalen Lösung für mein Problem. Für Hinweise, wie ich einen solchen Heartbeat effektiv schreiben könnte, wäre ich sehr dankbar.
Genau so hatte ich mir das vorgestellt um zu prüfen welche Peers im Netzwerk gerade das Programm laufen lassen und mit eben jenen dann interagieren zu können.
Es lebe der Informationskommunismus ! :)
Meine Jabber ID : Gromobir@draugr.de
rafael
User
Beiträge: 189
Registriert: Mittwoch 26. Juli 2006, 16:13

Gromobir
User
Beiträge: 9
Registriert: Donnerstag 14. Oktober 2004, 21:20

Guten Tag,
Ja, so etwas habe ich gesucht. :)
Nun bleibt nur noch ein kleines Problem:
Bei deinem aufgezeigten Beispiel sendet der Client immer an einen Server, dessen IP-Adresse bereits vorher bekannt war.
Nun möchte ich jedoch, dass der Client an alle verbundenen Peers sendet.
Ich nehme an, dass das nur per Broadcast bzw. Multicast zu realisieren ist oder kennt ihr noch andere Methoden?
Es lebe der Informationskommunismus ! :)
Meine Jabber ID : Gromobir@draugr.de
Antworten