Seite 1 von 1
Länge gesendeter Daten?
Verfasst: Mittwoch 16. September 2015, 18:16
von Alfons Mittelmeyer
Wenn ich empfange mit:
und wenn dann die Länge der Daten kleiner als 32 ist, dann müßte ich alles empfangen haben. Aber wenn die Länge der Daten gleich 32 ist, wie weiss ich dann, ob nur 32 Daten gesendet wurden oder ich noch nicht alles gelesen habe?
Sollte man am Anfang einer Message die Datenlänge übertragen, oder kann man das auch noch auf andere Art feststellen? Da ich ein Bytearrray haben will, scheidet so etwas wie EOL aus.
Re: Länge gesendeter Daten?
Verfasst: Mittwoch 16. September 2015, 18:21
von BlackJack
@Alfons Mittelmeyer: Wenn die Länge kleiner als 32 (aber mindestens 1) ist musst Du *nicht* alles empfangen haben. Du musst so oft `recv()` aufrufen bist Du sicher bist das Du alles empfangen hast und zwar entweder weil Du weisst wieviele Bytes kommen sollen oder weil Du das an den empfangenen Daten sehen kannst ob sie vollständig sind. Der Code muss so geschrieben sein das ``recv(32)`` im Extremfall bei jedem Aufruf nur 1 Byte liefert.
Re: Länge gesendeter Daten?
Verfasst: Mittwoch 16. September 2015, 18:52
von Alfons Mittelmeyer
@BlackJack Danke, hatte ich mir fast gedacht, denn das ist ein Beispiel aus tinyrpc:
Code: Alles auswählen
def _read_n_bytes(sock, n):
buf = []
while n > 0:
data = sock.recv(n)
n -= len(data)
buf.append(data)
return ''.join(buf)
Muss ich dann auch so machen, nur dann mit fester Bufferlänge, will schließlich nicht einige MB und b''.join(buf)
Ach so, wie lange darf ein Array sein? Ich danke da an MP3 Dateien, Begrenzung auf 64 KB oder nicht?
Re: Länge gesendeter Daten?
Verfasst: Mittwoch 16. September 2015, 19:08
von Sirius3
@Alfons Mittelmeyer: Pufferlängen von einigen MB sind unproblematisch. Aber wenn Du MP3-Dateien übertragen willst, ist wohl ein Streaming-Protokoll besser geeignet als ein Block-Protokoll.
Re: Länge gesendeter Daten?
Verfasst: Mittwoch 16. September 2015, 19:12
von Alfons Mittelmeyer
Sirius3 hat geschrieben:@Alfons Mittelmeyer: Pufferlängen von einigen MB sind unproblematisch. Aber wenn Du MP3-Dateien übertragen willst, ist wohl ein Streaming-Protokoll besser geeignet als ein Block-Protokoll.
Das wäre eigentich mehr gedacht um PDF Dateien an mehrere Schüler zu übertragen, wollte nur wissen, welche Längen gehen. Ein Streaming Protokoll möchte ich freilich auch noch haben. Das werde ich dann aber nicht selber machen.
Re: Länge gesendeter Daten?
Verfasst: Mittwoch 16. September 2015, 22:39
von Alfons Mittelmeyer
Habe jetzt die Lesefunktion von readline umgestellt auf Byte-Array mit Längenangabe:
Code: Alles auswählen
def read_message(self,socket):
buf = []
# get length
n = 4
while n > 0:
data = socket.recv(n)
if len(data) == 0: return None
n -= len(data)
buf.append(data)
n = int.from_bytes(b''.join(buf), byteorder='big')
# get data
while n > 0:
if n > 1024: buflen = 1024
else: buflen = n
data = socket.recv(buflen)
if len(data) == 0: return None
n -= len(data)
buf.append(data)
return b''.join(buf)
Re: Länge gesendeter Daten?
Verfasst: Mittwoch 16. September 2015, 23:25
von snafu
@Alfons: Dein Code ist problematisch. Stell dir vor, was wohl passiert, wenn du aus irgendwelchen Gründen beim erten `recv()` nur 3 Bytes empfängst? Dann holst du dir im nächsten Versuch wieder 4 Bytes und somit 3 Bytes zuviel. Abgesehen davon, dass es bei der nachfolgenden Operation für die Ermittlung der Länge dann ohnehin krachen würde, setzt sich der Fehler auch fort, da halt die ersten 3 Bytes des Contents versehentlich schon abgegriffen wurden. Somit würden deinem Content 3 Bytes vorne fehlen.
Re: Länge gesendeter Daten?
Verfasst: Mittwoch 16. September 2015, 23:27
von BlackJack
@Alfons Mittelmeyer: Ich würde ja immer noch die `makefile()`-Methode verwenden, dann muss man das nicht alles selbst neu erfinden und es ist ein bisschen weniger Code (ungetestet):
Code: Alles auswählen
def read_message(socket):
in_file = socket.makefile('rb')
return in_file.read(int.from_bytes(in_file.read(4), byteorder='big'))
@snafu: Wieso würden beim nächsten Versuch wieder 4 Bytes gelesen? `n` wird doch nach jedem `recv()`-Aufruf um die Anzahl der tatsächlich damit empfangenen Bytes verringert.
Re: Länge gesendeter Daten?
Verfasst: Mittwoch 16. September 2015, 23:33
von snafu
Stimmt. Habe den Code falsch gelesen.
Re: Länge gesendeter Daten?
Verfasst: Donnerstag 17. September 2015, 12:51
von Alfons Mittelmeyer
@BlackJack Dein Code würde mir auch besser gefallen, leider bekomme ich da folgenden Fehler: TypeError: cannot convert unicode object to bytes
Und wenn ich noch bytearray reinschalte, bekomme ich einen anderen Fehler: TypeError: string argument without an encoding
Das mag einfach nicht in Bytes lesen. Hab es mit bytes und 'utf-8' probiert, dann kommt das Programm zwar einmal darüber hinweg, setzt aber später wieder aus.
Am Besten man liest wirklich in Bytes ohne irgendwie utf-8, wenn es Bytes sind.
Das geht wohl in Python 2.x bei Python3.x will es einfach so nicht.
Komisch ist aber, dass vom File lesen in Bytes noch geht:
Code: Alles auswählen
fh = open("foto.jpg","rb")
myjpg = bytearray(fh.read())
fh.close()
Re: Länge gesendeter Daten?
Verfasst: Donnerstag 17. September 2015, 13:03
von BlackJack
@Alfons Mittelmeyer: Den Fehler kann ich nicht nachvollziehen. Ich bekomme da Bytes. Das Problem muss ausserhalb dieser Funktion liegen.
Re: Länge gesendeter Daten?
Verfasst: Donnerstag 17. September 2015, 23:18
von Alfons Mittelmeyer
@BlackJack Welche Python Version benutzt Du? Ich bekomme unicode! Aber Sinn ergibt unicode in diesem Zusammenhang wohl nicht viel. Und die Rückverwandlung von einem Unicode String in Bytes klappt nicht.
Und was ich dabei benutze ist ganz normal:
Code: Alles auswählen
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((self.ROUTERHOST, self.ROUTERPORT))
Sollte also wohl an der Python Version liegen. Ich benütze 3.2.4
Re: Länge gesendeter Daten?
Verfasst: Freitag 18. September 2015, 11:41
von BlackJack
@Alfons Mittelmeyer: Interessant ist weniger die Verbindung sondern ob Du beim `makefile()` auch sagst das Du Bytes haben möchtest.
Re: Länge gesendeter Daten?
Verfasst: Freitag 18. September 2015, 12:47
von Alfons Mittelmeyer
BlackJack hat geschrieben:@Alfons Mittelmeyer: Interessant ist weniger die Verbindung sondern ob Du beim `makefile()` auch sagst das Du Bytes haben möchtest.
Vielleicht hatte ich das gestern vergessen. Habe es heute probiert mit:
Code: Alles auswählen
def read_message(socket):
in_file = socket.makefile('rb')
number = in_file.read(4)
return number + in_file.read(int.from_bytes(number, byteorder='big'))
Beim Client hatte es funktioniert. Aber beim Router fehlten dann Daten. Habe auch teilweise leer empfangen. Geht unter gewissen Bedingungen aber unter anderen auch nicht. Zumindest nicht beim socketserver.BaseRequestHandler in Verbindung mit ThreadingMixIn. Da bleibe ich dann am Besten bei meiner Routine
Re: Länge gesendeter Daten?
Verfasst: Freitag 18. September 2015, 13:01
von Alfons Mittelmeyer
Habe mir gestern QPython auf dem Handy installiert. Und dann Fileübertragung getestet. 60 MB in 40 Sekunden waren nicht übel. Habe es dann heute mit Streaming gemacht. Das heißt, ich habe nicht den ganzen File auf einmal übertragen, sondern in 1 MB Blöcken. Da hatte es dann nur mehr etwa 20 Sekunden gedauert, weil man da nach dem ersten Block schon anfangen kann zu speichern. Das Sendeprogramm ist relativ einfach. Hier wird ein File auf dem PC geöffnet und dann dem Handy mitgeteilt, dass es einen zum Schreiben öffnen soll:
Code: Alles auswählen
file_handle = open("music.mp3","rb")
client.send("OPEN","/storage/extSdCard/tcp/music.mp3")
Und dann braucht man nur noch eine read Routine, über die das Programm auf dem Handy weitere Blöcke lesen kann:
Code: Alles auswählen
def read_block(message):
global file_handle
global block_nr
print("Block: ", block_nr)
block_nr += 1
block = file_handle.read(1000000)
if len(block) != 0: client.send("BLOCK",block)
else:
file_handle.close()
client.send("EOF")
client.do_receive("READ",read_block)
Und wenn das Programm auf dem Handy Blöcke zwischenbuffert, dann braucht es nach Schreiben eines Blockes nicht erst auf den nächsten warten.