L'envoi d'image sur les sockets (SEULEMENT) en Python, l'image ne peut pas être ouvert

Je veux télécharger l'image du client vers le serveur en utilisant UNIQUEMENT des sockets en Python. J'ai conçu un très simple protocole de flux de la façon dont je voudrais faire ceci:

CLIENT                                       SERVER
               SIZE 512 (send image size)
         ---------------------------------->
                      GOT SIZE   
         <---------------------------------- 
                 send image itself
         ---------------------------------->
                      GOT IMAGE
         <----------------------------------
                      BYE BYE 
         ---------------------------------->
                server closes socket

Voici mon code client:

#!/usr/bin/env python

import random
import socket, select
from time import gmtime, strftime
from random import randint

image = "tux.png"

HOST = '127.0.0.1'
PORT = 6666

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (HOST, PORT)
sock.connect(server_address)

try:

    # open image
    myfile = open(image, 'rb')
    bytes = myfile.read()
    size = len(bytes)

    # send image size to server
    sock.sendall("SIZE %s" % size)
    answer = sock.recv(4096)

    print 'answer = %s' % answer

    # send image to server
    if answer == 'GOT SIZE':
        sock.sendall(bytes)

        # check what server send
        answer = sock.recv(4096)
        print 'answer = %s' % answer

        if answer == 'GOT IMAGE' :
            sock.sendall("BYE BYE ")
            print 'Image successfully send to server'

    myfile.close()

finally:
    sock.close()

Et mon serveur, qui reçoit des images à partir de clients:

#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 6666
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if txt.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size'
sock.send("GOT SIZE")
elif txt.startswith('BYE'):
sock.shutdown()
elif data:
myfile = open(basename % imgcounter, 'wb')
data = sock.recv(40960000)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.send("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()

Pour l'image par exemple:

L'envoi d'image sur les sockets (SEULEMENT) en Python, l'image ne peut pas être ouvert

Le client imprime des messages, qui suggèrent, qu'à lui envoyer l'image vers le serveur avec succès:

answer = GOT SIZE
answer = GOT IMAGE
Image successfully send to server

L'image est créée à côté du serveur, mais je ne peux pas l'ouvrir. Et oui, j'ai essayé différentes images. Sans succès. Je ne peux pas les ouvrir au côté du serveur, même si elles y sont disponibles.

Grâce à @BorrajaX, j'ai réussi à le faire fonctionner! Merci! 🙂

#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 6666
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if data:
if data.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size'
sock.sendall("GOT SIZE")
elif data.startswith('BYE'):
sock.shutdown()
else :
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
data = sock.recv(40960000)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
Sans tester (et c'est pourquoi je ne l'ai pas la réponse) il ressemble dans le serveur que vous êtes l'obtention de la première 4096 octets dans votre data variable, mais ceux qui ne sont jamais écrite dans le fichier. Dans le elif data: vous écraser data avec data = sock.recv(40960000), de sorte que la première 4096 ne sont jamais écrite dans le myfile fichier. Peut-être est-ce?
Oui, c'était ça! J'ai ajouté myfile.write(data) juste après la myfile = open(basename % imgcounter, 'wb') ligne et maintenant je peux ouvrir l'image! 🙂 Mais, de son tout semble laid maintenant (le code). Avez-vous une idée de comment l'améliorer? Pour ne pas avoir deux myfile.write(data)?
Et comment puis-je éviter les erreurs lorsque le client envoie quelque chose de différent que les messages définis dans le protocole et l'image? Je veux juste déconnecter dans de tels cas.
Eh bien... pour améliorer... je suppose qu'on peut toujours nettoyer un peu l'écriture des données à l'aide de with open(basename % imgcounter, 'wb') as myfile. Pour éviter les erreurs... Car vous ne savez pas ce que data est (binaire) ce que je voudrais faire est de vérifier (après la lecture de tout) que data est réellement une image. Jetez un oeil à la LIP (pypi.python.org/pypi/PIL)

OriginalL'auteur yak | 2017-02-25