Posts: 203
Threads: 41
Joined: Mar 2019
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()
Posts: 4,529
Threads: 69
Joined: Jan 2018
Nov-07-2019, 08:23 AM
(This post was last modified: Nov-07-2019, 08:48 AM by Gribouillis.)
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()
Posts: 203
Threads: 41
Joined: Mar 2019
Nov-07-2019, 09:49 AM
(This post was last modified: Nov-07-2019, 09:49 AM by mcgrim.)
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
Posts: 4,529
Threads: 69
Joined: Jan 2018
Nov-07-2019, 10:12 AM
(This post was last modified: Nov-07-2019, 10:15 AM by Gribouillis.)
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.
Posts: 203
Threads: 41
Joined: Mar 2019
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.
Posts: 4,529
Threads: 69
Joined: Jan 2018
Nov-07-2019, 11:43 AM
(This post was last modified: Nov-07-2019, 11:44 AM by Gribouillis.)
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'
Posts: 203
Threads: 41
Joined: Mar 2019
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
Posts: 4,529
Threads: 69
Joined: Jan 2018
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.
Posts: 203
Threads: 41
Joined: Mar 2019
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()
Posts: 4,529
Threads: 69
Joined: Jan 2018
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.
|