Python Forum
send all pictures instead of just two
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
send all pictures instead of just two
#1
The server is supposed to send all pictures from a folder to the client.
By changing the number inside of the parenthesis of s.recv() in the client side
I was able to display two pictures.
My question is, what is stopping my code from sending/displaying them all?
How to fix it?
P.S.
the number inside the parenthesis is the size of one of the pictures.

SERVER
import socket
import glob
import os

host = "127.0.0.1"
port = 5000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(5)
print("server started...")

path1 = (r"C:\Users\Desktop\opencvpics")

def readFileImages():
    st = os.path.join(path1, "*.jpg")
    print(st)
    return glob.glob(st)

list1 = readFileImages()

print(list1, "list1......")

while True:
    c, addr = s.accept()
    #print(f"connection from {addr} has been established !")
    #c.send(bytes("welcome to the server".encode()))

    for pics in (readFileImages()):
        f = open(pics, 'rb')
        l = f.read()

        #while (l):
        c.sendall(l)
        #print('Sent ', repr(l))
        print(len(l), 'LENGTH L')
        print(f, "how many files")

        f.close()


    print('Done sending')
    c.send('Thank you for connecting'.encode())
CLIENT

import socket
from PIL import Image
import io

host =  "127.0.0.1"
port = 5000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

s.send('Hello server!'.encode())

with open('received_file.jpg', 'wb') as f:
    print('file is open')

    while f:

        print('receiving data...')
        #data = s.recv(439813)
        data = s.recv(440179)
        print('data=%s', data, "ASDFASDSADFASDFVSSDSAFSADDFDSAFD")
        f.write(data)
        print('Successfully get the files')
        print('connection closed')
        print(type(data))
        print(len(data))

        image = Image.open(io.BytesIO(data))

        image.show()


s.close()
Reply
#2
I think you should try to send the data by smaller chunks. Try to run the following (untested) code and see if all the bytes are sent and received:
# SERVER CODE
import socket
import glob
import os
 
host = "127.0.0.1"
port = 5000
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(5)
print("server started...")
 
path1 = (r"C:\Users\Desktop\opencvpics")
 
def readFileImages():
    st = os.path.join(path1, "*.jpg")
    print(st)
    return glob.glob(st)
 
def binary_chunks(filename, chunksize=4096):
    with open(filename, 'rb') as f:
        while True:
            s = f.read(chunksize)
            if not s:
                return
            yield s

 
while True:
    c, addr = s.accept()
    #print(f"connection from {addr} has been established !")
    #c.send(bytes("welcome to the server".encode()))
    grand_total = 0
    
    for pics in readFileImages():
        print('Sending', pics)
        sent = 0
        for chunk in binary_chunks(pics):
            c.sendall(chunk)
            sent += len(chunk)
        print("Sent {} bytes for {}".format(sent, pics))
        grand_total += sent
    print('Done sending')
    print('A total of {} bytes were successfully sent.'.format(grand_total))
    c.close()
Client code:
##### CLIENT CODE

import socket
from PIL import Image
import io
 
host =  "127.0.0.1"
port = 5000
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

received = 0
while True:
    chunk = s.recv(4096)
    if not chunk:
        break
    received += len(chunk)
print('Finished receiving. In total, {} bytes were received'.format(received))
s.close()
Reply
#3
It looks like the bytes are transferred, thank you, but now I am not sure how to implement the image show algorithm.

I tried to change the client this way:
import socket
from PIL import Image
import io

host = "127.0.0.1"
port = 5000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

with open('received_file.jpg', 'wb') as f:
    print('file is open')
    chunk = s.recv(4096)
    f.write(chunk)

    received = 0
    while True:
       # chunk = s.recv(4096)
        if not chunk:
            break
        received += len(chunk)
        f.write(chunk)
        image = Image.open(io.BytesIO(chunk))

        image.show()
print('Finished receiving. In total, {} bytes were received'.format(received))
s.close()
but I get this error
Error:
Traceback (most recent call last): File "C:/Users/PycharmProjects/client-server/client_3.py", line 23, in <module> image = Image.open(io.BytesIO(chunk)) File "C:\Users\PycharmProjects\client-server\venv\lib\site-packages\PIL\Image.py", line 2818, in open raise IOError("cannot identify image file %r" % (filename if filename else fp)) OSError: cannot identify image file <_io.BytesIO object at 0x02F81FC0> Process finished with exit code 1
Reply
#4
The problem with using raw sockets is that you need to define your own communication protocol. Here you need some way to tell the client how to separate the images in the data flow. The solution is to send some structured data. For example instead of sending the raw data b'foo-spam-egg' which has length 12, you could send b'12:foo-spam-egg'. The client would know that it must read until b':', then read 12 bytes of data. At the end on each image, you could send a chunck such as b'end:' and the client is now able to distinguish image data from out of band data.

Here is an untested (which means probably broken) implementation for this. See if it works
# SERVER CODE
import socket
import glob
import os
 
host = "127.0.0.1"
port = 5000
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(5)
print("server started...")
 
path1 = (r"C:\Users\Desktop\opencvpics")
 
def readFileImages():
    st = os.path.join(path1, "*.jpg")
    print(st)
    return glob.glob(st)
 
def binary_chunks(filename, chunksize=4096):
    with open(filename, 'rb') as f:
        while True:
            s = f.read(chunksize)
            if not s:
                return
            yield s

def send_item(c, chunk):
    prefix = str(len(chunk)).encode()
    c.sendall(prefix + b':' + chunk)
 
while True:
    c, addr = s.accept()
    #print(f"connection from {addr} has been established !")
    #c.send(bytes("welcome to the server".encode()))
    grand_total = 0
    
    for pics in readFileImages():
        print('Sending', pics)
        sent = 0
        for chunk in binary_chunks(pics):
            send_item(c, chunk)
            sent += len(chunk)
        c.sendall(b'end:')
        print("Sent {} bytes for {}".format(sent, pics))
        grand_total += sent
    print('Done sending')
    print('A total of {} bytes were successfully sent.'.format(grand_total))
and the client part
##### CLIENT CODE

import socket
from PIL import Image
import io
 
host =  "127.0.0.1"
port = 5000
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))


received = 0
buf = [b'']

def get_item(s, buf=buf):
    acc = buf[0]
    while not b':' in acc:
        acc += s.recv(4096)
    prefix, acc = acc.split(b':', 1)
    n = O in prefix == b'end' else int(prefix)
    while len(acc) < n:
        acc += s.recv(4096)
    buf[0] = acc[n:]
    return (prefix, acc[:n])

while True:
    prefix, chunk = get_item()
    received += len(chunk)
    if prefix == b'end':
        print('End of image')
print('Finished receiving. In total, {} bytes were received'.format(received))
s.close()
For me the conclusion is that you are better off using a more structured alternative to raw sockets. There are many. For local usage you could try an xmlrpc server for example or a http server among other possible choices, such as a SSH server.
Reply
#5
May you please tell me what line 22 does ?
there are some bugs there, but if you tell me what is meant to do
I can perhaps rewrite it.
Reply
#6
Line 22 in the client code is equivalent to
if prefix == b'end':
    n = 0
else:
    n = int(prefix)
I see the problem: 'in' should be 'if'
Reply
#7
with this code, the files are transferred, but I am now not sure how to display images.
Implementing this code after line 35

image = Image.open(io.BytesIO(b'received'))

        image.show()
gives me the same error that I first posted
Reply
#8
I don't know if I can answer this question. Try to post the exact code that you're using, but I'll be away for a few hours.
Reply
#9
here is the client.
The server is the same.

##### CLIENT CODE

import socket
from PIL import Image
import io

host = "127.0.0.1"
port = 5000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

received = 0
buf = [b'']


def get_item(s, buf=buf):
    acc = buf[0]
    while not b':' in acc:
        acc += s.recv(4096)
    prefix, acc = acc.split(b':', 1)
    if prefix == b'end':
        n = 0
    else:
        n = int(prefix)
    while len(acc) < n:
        acc += s.recv(4096)
    buf[0] = acc[n:]
    return (prefix, acc[:n])

with open('received_file.jpg', 'wb') as f:
    print('file is open')
    data = s.recv(440179)
    f.write(data)
    while True:
        prefix, chunk = get_item(s)
        received += len(chunk)
        if prefix == b'end':
            image = Image.open(io.BytesIO(b'chunk'))

            image.show()
            print('End of image')
            print('Finished receiving. In total, {} bytes were received'.format(received))
    s.close()
Reply
#10
Why do you have this data = s.recv(440179) or this image = Image.open(io.BytesIO(b'chunk')). It looks like you don't understand what the code does. Write only code that you fully understand otherwise it won't run.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020