RPC Dateihandler für Kopieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Ich möchte eine Datei von Rechner A auf Rechner B kopieren. Rechner A hat weder einen File- noch Webserver. Ich hab mich gefragt ob es möglich ist, auf Rechner A einen Filehandler auf die Datei zu erstellen und diesen serialisiert über RPC zu Rechner B zu übertragen. Kann Rechner B den Filehandler wieder deserialisieren und damit auf den Dateiinhalt zugreifen, der sich ja noch auf Rechner A befindet? Somit könnte man die Datei häppchenweise einlesen und auf Rechner B schreiben, bis EOF erreicht ist.

Oder gibt es noch andere, elegante Möglichkeiten, eine Datei mit reinen Python-Mitteln zu kopieren, z.B. über copy?
BlackJack

Dateihandles sind Interna des Betriebssystems. Unter Linux/Unix kann man die nicht einmal unter Prozessen austauschen, geschweige denn über das Netz. Und man kann Dateiobjekte nicht einmal lokal serialisieren.

Die einfachste Lösung wäre das "streamen" der Daten über eine TCP-Verbindung oder Du startest einen Python-Webserver und holst die Datei auf der anderen Seite mit `urllib2`.
tuxthekiller
User
Beiträge: 18
Registriert: Samstag 2. Dezember 2006, 12:17

Ich würde es mit Sockets machen:

Server:

Code: Alles auswählen

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', -=port=-))
sock, addr = s.accept()

length = ''
while 1:
    l = sock.recv(1)
    if l == '\n': break
    length = length + l

data = sock.recv(int(length))
Client:

Code: Alles auswählen

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
data = f.read # oder so ;)
length = len(data)
s.send(length)
s.send(data)
Ungetestet.

EDIT: Vielleicht ist das mit der Länge unnötig und du kannst sock.recv(999999999999999) nehmen. ;)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

droptix hat geschrieben:Ich möchte eine Datei von Rechner A auf Rechner B kopieren. Rechner A hat weder einen File- noch Webserver.
Hi droptix!

Wenn Rechner B einen Fileserver hat, dann kannst du Rechner A als Client einrichten und von Rechner A aus Dateien zum Rechner B hochschieben oder Dateien von Rechner B kopieren.

Wenn du mit Bortmitteln eine Datei kopieren kannst. Z.B. mit dem Explorer oder mit COPY (Windows) oder unter Linux mit dem Nautilus oder mit "cp", dann kannst du das auch mit Python machen. Dann kommt es noch darauf an, von wo aus du die Datei kopieren möchtest.

Du kannst aber jederzeit Python zum kopieren verwenden, wenn auf einem der Computer ein Serverprogramm und auf dem anderen Computer ein Clientprogramm gestartet werden. Dafür gibt es dann richtig viele Möglichkeiten: Socket, XMLRPC, JsonRPC, HTML, FTP,...

Wenn du mit SSH auf die Computer zugreifen kannst, dann kannst du das Programm "scp" zum Kopieren verwenden.

usw.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

Wenn schon ein socket Beispiel, dann schon ein funktionierendes.

Server:

Code: Alles auswählen

import socket
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 41000))
s.listen(1)
sock, addr = s.accept()

#Dateigrösse empfangen
data = sock.recv(struct.calcsize('Q'))
size = struct.unpack('Q', data)[0]

#Dateiname empfangen
data = sock.recv(struct.calcsize('I'))
name_len = struct.unpack('I', data)[0]
name = sock.recv(name_len)


f = open(name+'.bak', 'wb')
read = 0
while read < size:
    data = sock.recv(min(size-read, 102400))
    read += len(data)
    f.write(data)

f.close()
sock.close()
s.close()
Client:

Code: Alles auswählen

import socket
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 41000))

filename = 't.py'

f = open(filename,'rb')
f.seek(0,2)
filesize = f.tell()
f.seek(0,0)

#Dateigrösse übertragen
s.send(struct.pack('Q', filesize))

#Länge von Dateiname übertragen
s.send(struct.pack('I', len(filename)))

#Dateiname übertrage
s.send(filename)

while f.tell() < filesize:
    #Datei in 100k Blöcke übertragen
    s.send(f.read(1024*100))

s.close()
f.close()
Datei wird vom Client zum Server geschickt

Gruss
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Danke für diese Einführung :wink:

Also wäre es wohl das Sinnvollste, wenn ich einen Fileserver in Python baue, zu dem sich Clients verbinden. Momentan mach ich das mit XMLRPC, aber wegen Base64 werden die Daten ja um ein Drittel aufgebläht. Daher will ich die Daten lieber "direkt" rüberschieben.

Welches Protokoll eignet sich da am besten bzw. welches ist am effizientesten/am schnellsten?

Kann man einen SSL-Fileserver in Python bauen, der die Verbindung verschlüsselt?
BlackJack

Am einfachsten zu schreiben dürfte wahrscheinlich ein HTTP-Server werden, da Python schon eine gute und im Grunde komplette Lösung in der Standardbibliothek hat. Binärdaten können damit auch effizient übermittelt werden und den "Client"-Teil findet man in `urllib` oder `urllib2` bzw. kann man auch jeden Browser verwenden. Ob man in den Server auf einfache Weise SSL-Verschlüsselung bekommt, weiss ich allerdings nicht.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Ob man in den Server auf einfache Weise SSL-Verschlüsselung bekommt, weiss ich allerdings nicht.
Zur Not kann man auch recht einfach stunnel an beiden Enden nutzen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Hum, bei einem HTTP-Server könnte aber jeder mit einem gewöhnlichen Browser Dateien anfordern, richtig? Ich will nicht, dass jeder Zugriff bekommt -> Wie kann ich den HTTP-Zugriff mit einem Passwort absichern und könnte man das Passwort mitsniffen?

Ich möchte eher vom Client aus eine ID anfordern. Der Server schaut nach ob es ein ZIP-Archiv zu dieser ID gibt. Zusätzlich zur ID fragt der Client noch nach einem Dateinamen. Existiert diese Datei im ZIP-Archiv, soll daraus nur diese eine Datei zum Client übertragen werden.

Also fordert der Client nicht direkt eine Datei an, sondern liefert nur Infos, aus denen der Server Rückschlüsse auf eine Datei zieht. Vor der Dateiübertragung muss also eine Auswertung stattfinden.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

droptix hat geschrieben:Hum, bei einem HTTP-Server könnte aber jeder mit einem gewöhnlichen Browser Dateien anfordern, richtig? Ich will nicht, dass jeder Zugriff bekommt -> Wie kann ich den HTTP-Zugriff mit einem Passwort absichern und könnte man das Passwort mitsniffen?
Du kannst den Zugriff auf bestimmte IPs einschränken. Für die Übermittlung von Passwörtern gibt es im HTTP-Protokoll die Möglichkeit, aber BaseHTTPServer/SimpleHTTPServer unterstützten diese soweit ich weiß nicht. Wenn doch, kannst du die HTTP-Verbindung in einen SSL-Tunnel stecken und dann wird das Passwort nicht mehr in Klartext über das Netzwerk übertragen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Leonidas hat geschrieben:kannst du die HTTP-Verbindung in einen SSL-Tunnel stecken
Tja wie? Ginge das mit reinen Python-Mitteln? Man bräuchte ja einen HTTP-Server mit SSL-Unterstützung. Und der Client muss ja eine https-Verbindung verlangen.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

droptix hat geschrieben:Ginge das mit reinen Python-Mitteln? Man bräuchte ja einen HTTP-Server mit SSL-Unterstützung.
Hi droptix!

Der Apache kann das. Und der ist nicht umsonst so ein umfangreiches Programm. Du könntest aber auch einen OpenVPN-Tunnel zwischen den Clients erstellen. -- Auch nicht mit Python. Warum? Weil es dafür fertige Programme gibt.

Aber ich weiß nicht was du machen willst. Deshalb hier ein Link aus dem Jahr 2001: http://archiv.tu-chemnitz.de/pub/2001/0 ... de123.html

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Einen Apache beim Kunden vorauszusetzen halte ich bei einer simplen Datenübertragung für übertrieben.

Der Link ist interessant, allerdings scheint man dafür OpenSSL zu benötigen. Das schränkt mich dann auch wieder ein.

Was ich machen will: der Client soll Dateien beim Server anfordern. Der Server soll sie rausrücken. Das Problem dabei: man soll nicht in der Lage sein, die Dateien mit einem anonymous FTP-Zugang oder einem Browser abzurufen. Selbst wenn man serverseitig einen FTP-Server realisiert kann man das Passwort im Klartext mitsniffen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

droptix hat geschrieben:Ginge das mit reinen Python-Mitteln? Man bräuchte ja einen HTTP-Server mit SSL-Unterstützung.
Dafür gibt es das Rezept Simple HTTP server supporting SSL secure communications im Cookbook - allerdings benötigst du dazu pyopenssl.
gerold hat geschrieben:Du könntest aber auch einen OpenVPN-Tunnel zwischen den Clients erstellen. -- Auch nicht mit Python. Warum? Weil es dafür fertige Programme gibt.
Ein solches externes Programm ist stunnel, welches den Vorteil hat, dass ein Server der nur HTTP hat, in einen stunnel gepackt zu ganz normalen HTTPS wird. So braucht es nicht immer eine "Gegenstelle" wie das bei OpenVPN nötig ist.

Wie man die von HTTP vorgesehene Basic Authentification macht musst du selbst herausfinden. Ich habe bisher nur wsgiAdapter gefunden, der sowas Server-Seitig implementiert. :(
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Hum, wenn ich mir das nochmal überlege könnte der SimpleHTTPServer doch ausreichen. Allerdings müsste ich anstatt eine Datei anzufordern lediglich POST-Parameter übermitteln und der Server müsste diese auswerten.

Ich darf keine direkte Datei anfordern, aber das geht ja schlecht :) Verarbeitet der SimpleHTTPServer auch .py- bzw. .pyc-Dateien? Oder werden die dann zum Client übertragen?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

droptix hat geschrieben:Verarbeitet der SimpleHTTPServer auch .py- bzw. .pyc-Dateien?
Hi droptix!

Ja, wenn du ihn als CGI-Server verwendest.
- http://www.python-forum.de/post-66081.html#66081
- http://docs.python.org/lib/module-cgi.html

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten