tcp datei übertragung

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
ceddy
User
Beiträge: 79
Registriert: Mittwoch 25. August 2010, 12:01

Ich übertrage über Tcp eine Bild-Datei, es funktioniert auch alles, außer, das der empfänger der Datei in der Schleife zum empfangen der einzelnen blocks hängen Bleibt

Sender:

Code: Alles auswählen


					image=ImageGrab.grab()
					image.save("C:/test.bmp","bmp")
					imageFile=open("C:/test.bmp","rb")
					block="x"
					while block:
							block=imageFile.read(1024)
							if(block<>None):
								s.send(block)
					print "jo"					
					imageFile.close()	


Empfänger:

Code: Alles auswählen


						file=open("test.bmp","wb")
						x=client.recv(1024)
						while True:
							if x:
								print" ...."
								file.write(x)
								x=client.recv(1024)
							else:								
								break
						print"Uebertragung abgeschlossen"
Kann mir jemand sagen was falsch ist?

ceddy
BlackJack

@ceddy: Woher soll der Empfänger wissen wann die Daten zuende sind? Du müsstest beim Sender nach den letzten Daten das `socket` schliessen, sondern wartet der Empfänger ewig ob da noch etwas kommt.
ceddy
User
Beiträge: 79
Registriert: Mittwoch 25. August 2010, 12:01

Der scoket soll ja nciht geschlossen werden, da irgendwann weiter daten übertragen werden sollen
BlackJack

@ceddy: Dann musst Du Dir ein Protokoll ausdenken bei dem der Sender dem Empfänger kommunizieren kann wie viele Daten er lesen muss oder wann er aufhören kann. Woher soll der Empfänger, wie schon gefragt, sonst wissen wann die Daten für das eine Bild zu Ende sind?
ceddy
User
Beiträge: 79
Registriert: Mittwoch 25. August 2010, 12:01

Ich hab das jetzt so gemacht

Sender:

Code: Alles auswählen

		image=ImageGrab.grab()
		image.save("C:/ss.bmp","bmp")
		imageFile=open("C:/ss.bmp","rb")
		block="x"
		while block:
			block=imageFile.read(1024)
			self.s.send(block)
		self.s.send("EOF")					
		imageFile.close()
Empfänger:

Code: Alles auswählen

		file=open("ss.bmp","wb")
		print "Screenshot wird heruntergeladen"
		x=self.client.recv(1024)
		while (x<>"EOF"):
			file.write(x)
			x=self.client.recv(1024)
		file.close()		
		print"Uebertragung abgeschlossen"
Aber irgendwas muss immer noch falsch sein :/
BlackJack

@ceddy: Die Bytewerte für die Zeichenfolge EOF könnten auch zufällig irgendwo in den Daten vorkommen. Ausserdem darfst Du nicht davon ausgehen, dass die Daten immer in 1024 Byte grossen „Häppchen” ankommen, nur weil Du sie in diesen Grössen beim Sender an die `socket`-API übergibst. Und selbst wenn dem so wäre, kann Dein Code nur funktionieren wenn die Byteanzahl der Bilddaten genau durch 1024 teilbar wäre, denn nur dann würde *genau* das EOF am Ende für einen einzigen `recv()`-Aufruf übrig bleiben.

Aber da Du sicherstellen musst, dass eine Endmarkierung niemals innerhalb der Nutzdaten vorkommen kann, ist das sowieso keine gute Idee. Besser Du überträgst am Anfang wie viele Daten zu dem Bild gehören. Und beim Empfänger musst Du auch damit rechnen mehr zu lesen — nämlich schon den Anfang vom nächsten Bild beziehungsweise die Daten, die sagen wie gross das ist (+ ein bisschen vom Anfang des Bildes).

Anstelle vom BMP-Format könntest Du auch über PNG nachdenken — das komprimiert besser. Sofern BMP überhaupt komprimiert ist.
ceddy
User
Beiträge: 79
Registriert: Mittwoch 25. August 2010, 12:01

Könnte mir jemand hrlfen wie man das umsetzen könnte?
BlackJack

@ceddy: Ungetestet:

Code: Alles auswählen

    # 
    # Sender
    # 
    data = ImageGrab.grab().tostring('png')
    self.socket_file.write('%d\n' % len(data))
    self.socket_file.write(data)
    self.socket_file.flush()
    
    
    # 
    # Empfänger
    # 
    size = int(self.socket_file.readline())
    image_data = self.socket_file.read(size)
    if len(image_data) != size:
        raise ValueError('incomplete image received')
    with open('ss.png', 'wb') as image_file:
        image_file.write(image_data)
Wobei `self.socket_file` das Ergebnis eines `makefile()`-Aufrufs auf dem ursprünglichen Socket ist. Denn sonst wird das ganze komplizierter, weil man sich mit den der Socket-API herumschlagen muss. Dein senden war bisher zum Beispiel nicht robust, weil `socket.send()` nicht garantiert, dass auch wirklich alle Daten gesendet werden die man übergibt. Man muss sich den Rückgabewert anschauen und gegebenenfalls `send()` so lange mit den jeweiligen Restdaten aufrufen, bis auch wirklich alles raus ist.
Antworten