I want to upload the image from client to server using ONLY sockets in Python. I designed a very simple protocol flow of how I would like to do this:
CLIENT                                       SERVER
               SIZE 512 (send image size)
         ---------------------------------->
                      GOT SIZE   
         <---------------------------------- 
                 send image itself
         ---------------------------------->
                      GOT IMAGE
         <----------------------------------
                      BYE BYE 
         ---------------------------------->
                server closes socket
Here's my client code:
#!/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()
And my server, which receives images from 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()
For the example image:

The client prints out messages, that suggest, that it send the image to server successfully:
answer = GOT SIZE
answer = GOT IMAGE
Image successfully send to server
The image is created at server's side, but I can not open it. And yes, I tried different images. With no success. I can't open them at server's side, even though they are available there.
Thanks to @BorrajaX, I managed to make it work! Thanks! :)
#!/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()
                You can send and receive on the same socket at the same time (via multiple threads). But the send and receive may not actually occur simultaneously, since one operation may block the other from starting until it's done.
Okay your problem is, in the case of actual image received, you are reading the socket two times and ignoring the data in the first read and just writing the data received in the second read. So your image file is incomplete. See my fix below , you can optimize from this taking it as starting point. It works as such.
#!/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)
buffer_size = 4096
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:
                print ' Buffer size is %s' % buffer_size
                data = sock.recv(buffer_size)
                txt = str(data)
                if txt.startswith('SIZE'):
                    tmp = txt.split()
                    size = int(tmp[1])
                    print 'got size'
                    print 'size is %s' % size
                    sock.send("GOT SIZE")
                    # Now set the buffer size for the image 
                    buffer_size = 40960000
                elif txt.startswith('BYE'):
                    sock.shutdown()
                elif data:
                    myfile = open(basename % imgcounter, 'wb')
                    # data = sock.recv(buffer_size)
                    if not data:
                        myfile.close()
                        break
                    myfile.write(data)
                    myfile.close()
                    sock.send("GOT IMAGE")
                    buffer_size = 4096
                    sock.shutdown()
            except:
                sock.close()
                connected_clients_sockets.remove(sock)
                continue
        imgcounter += 1
server_socket.close() 
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With