How to send images via socket in Python?

Asked

Viewed 1,193 times

0

So is the server:

import socket
from PIL import Image
port = 8000
host = '127.0.0.1'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.bind((host, port))
s.listen(5)



while True:
    conn, addr = s.accept()
    print('Conectado a {}'.format(addr))
    with open('logo_python.png', 'rb') as f:
        conn.send(f.read())
        l = f.read()
    #im = Image.open(l)
    #im.show()
        f.close()

print('Arquivo enviado')

And the customer:

import socket
from PIL import Image
host = '127.0.0.1'
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

print("Recebendo Dados...\n")
with open('recebido.png', 'wb') as f:
        print('file opened')
        print('Recebendo dados...')
        data = s.recv(4000)
        f.write(data)
        print(data)
        print("ENVIADO")
        f.close()
with open('recebido.png', 'rb') as f:
        im = Image.open(f)
        im.show()

print('Transferência completa!!!')
s.close()
print('Conexão encerrada.')

The error that appears:

    File "C:/Users/Diego Cândido/PycharmProjects/servarq/ClienteTeste.py", line 18, in <module>
    im = Image.open(f)
  File "C:\Users\Diego Cândido\AppData\Local\Programs\Python\Python37\lib\site-packages\PIL\Image.py", line 2618, in open
    prefix = fp.read(16)
  File "C:\Users\Diego Cândido\AppData\Local\Programs\Python\Python37\lib\encodings\cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 172: character maps to <undefined>

Basically what the server is sending to the client is:

b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02Y\x00\x00\x00\xcb\x08\x06\x00\x00\x00]\xc9\x86&\x00\x00\x00\x04sBIT\x08\x08\x08\x08 #... e assim por diante
  • The error you posted is incomplete - just put the error line, without the complete traceback. Traceback would be useful to know where exactly the error is occurring. You can edit the question and add.

  • You’re making print(f.read()) and then conn.send(f.read()) however f.read() only works once, the second time it returns nothing, because the file has already been read all over. If you want to use the file contents twice, you have to store it in a variable, rewind the file or open it again.

  • I will correct and put the new error

1 answer

1


EDIT: Now with the code and the error is much easier to help.

UnicodeDecodeError occurs when trying to turn into a string a byte sequence that does not match the encoding used.

From the error text, it seems that it is using the encoding charmap cp1252; this would only occur if you were trying to run the method .decode() or if you opened the file in text mode (not binary); when you open a file in text mode, python does the automatic decoding.

The code you put in the question has the letter 'b' in the open, indicating binary mode:

with open('recebido.png', 'rb') as f:

To check if there was any mistake, I did a test with a JPG file I downloaded here, called diego.jpg. I opened it in text mode, without the letter b:

>>> f = open('diego.jpg', 'r', encoding='cp1252') # sem o 'b'
>>> f.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/encodings/cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 383: character maps to <undefined>

As you can see the error was quite similar to yours - I believe that when testing, you must have confused the files and left the open() without the b, And that’s why you got the mistake you made, I can’t see any other reason.

I then resolved test your code above, but with that file diego.jpg I downloaded. I only changed the name of the logo_python.png for diego.jpg and ran the server.

I changed the name of the recebido.png for recebido.jpg and surrounded the customer. Gave the following error:

Traceback (most recent call last):
  File "cliente.py", line 19, in <module>
    im.show()
#  ( ... )
  File "/usr/lib/python3/dist-packages/PIL/Image.py", line 1982, in show
    _show(self, title=title, command=command)
  File "/usr/lib/python3/dist-packages/PIL/ImageFile.py", line 228, in load
    "(%d bytes not processed)" % len(b))
OSError: image file is truncated (3 bytes not processed)

As you can see, 4000 bytes is not enough to transfer the image. I once again edited the client, and increased the number to 6502 (which is exactly the image size diego.jpg):

deu certo!

In short: It worked, your code is "working", the error you are having is impossible to occur with the code the way you put in the question, there must be some mistake. The only thing I changed was the number of bytes, which should be exactly the size of the image, because with fewer bytes it is not possible to open the image.

  • I did what you said, but the error still appears: Typeerror: a bytes-like Object is required, not '_io.Bufferedreader'

  • I modified it to 6000 bytes, but it still gives the same problem.

  • Traceback (Most recent call last): File "C:/Users/Diego Cândido/Pycharmprojects/servarq/Servidorteste.py", line 20, in <module> im = Image.open(io.Bytesio(g)) Typeerror: a bytes-like Object is required, not '_io.Bufferedreader'

  • @Diegocandid this means that g in your error is not a variable containing bytes, but a BufferedReader. The type of variable you pass to io.BytesIO() has to be bytes, otherwise it will give this error you said. Try print(type(g)) to see what type of your variable.

  • It is not possible to read images partially, neither 1024 nor 6000 nor 100000 bytes, you need to read the image all, ALL bytes.

  • The type is <class '_io.Bufferedreader'. The problem is I don’t know what to send to the customer. Because if I send "g", it gives this problem, because it asks for bytes. But if I send socket.send(g.read()), there in the client, it also gives error. I don’t know how to send the image and I don’t know how the client should receive and show, because it passes as bytes.

  • @But where did you get that g?? In the code you put, there’s no g! Put your real code in the question, and the whole mistake, please!! Otherwise it gets very difficult to follow and help.

  • You can Edit the question and add information

  • Done! I updated the code.

  • @Diegocândido got show! Now just put the complete error, with traceback

  • Dude, I fixed the code and it’s giving you an error similar to yours: Oserror: image file is truncated (3 bytes not processed)

  • How did you find out the exact size of the image?

  • I found out! Man, thank you very much, it all worked out. You have no idea how much you helped me. Vlw!!!!

Show 8 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.