I can't send an image (socket & ngrok)

45 views Asked by At

Client:

from PIL import Image, ImageTk
from tkinter import *
import socket, threading, base64
window = Tk()
window.title('Stream')
window.geometry('810x540')
window.configure(bg='black')
def GetPic():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('localhost', 8000))
    server_socket.listen(1)
    client_socket, client_address = server_socket.accept()
    while True:

        #try:
        dir2 = r'C:\Users\SystemX\AppData\Local\Temp\screen_tr2.png'

        data = client_socket.recv(11111393216) # 
        data = base64.b64decode(data)
            
        with open(dir2, 'wb') as f:
                f.write(data)
                
        img = PhotoImage(file=dir2)
        lbl.configure(image=img)
        #except Exception as e:
        #    print(e)
            
#os.system(dir2)
lbl = Label(window, bg='black', image=None)
lbl.place(x=0,y=0)
threading.Thread(target=GetPic).start()
window.mainloop()

Server:

from PIL import ImageGrab
from tkinter import *
import socket, time, base64

dir = r'C:\Users\SystemX\AppData\Local\Temp\screen_tr.png'

ip, port = 'IP:PORT'.split(':')

timee=time.time()
print('started')
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((ip, int(port)))
while True:

    #time.sleep(2)
    screenshot = ImageGrab.grab()
    print(f'grabbed ({time.time() - timee}s)')
    screenshot.save(dir)
    print(f'saved ({time.time() - timee}s)')
    with open(dir, 'rb') as f:
        content = f.read()
        #print(content)
        enc = base64.b64encode(content)
        client_socket.send(enc)
        #client_socket.send(content)

#server_socket.close()

The image is interrupted during transmission. How can I fix this?

The image is not fully transmitted. ngrok appears to be disrupting the image. Maybe there are other suitable means of opening ports? When transferring an image without base64 decoding, the image also breaks.

1

There are 1 answers

0
Tim Roberts On

This will help you solve the socket part of your issue. I've changed the server so that it loops on the "read" until it returns 0, which happens when the socket closes. This allows it to receive the entire image. Note that I've added break to both loops so that it doesn't go forever. I've also removed the tkinter parts, to avoid confusing the issue too much.

Note that you have the "server" and "client" backwards. The one doing the "accept" is the server. The one doing "connect" is the client. I also removed the ImageGrab, since that doesn't work on Linux with Wayland, which I have.

Server:

from PIL import Image, ImageTk
import socket

BUF = 16384
def GetPic():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('localhost', 8000))
    server_socket.listen(1)
    client_socket, client_address = server_socket.accept()
    dir2 = 'p2.png'
    while True:
        data = b''
        while True:
            buf = client_socket.recv(BUF)
            if not buf:
                break
            data += buf
            print(len(buf),len(data))
            
        print('received',len(data),'bytes')
        with open(dir2, 'wb') as f:
            f.write(data)
        break

GetPic()

Client:

from PIL import ImageGrab
import socket, time, base64

dir = 'xxxxxx.png'

ip, port = 'localhost:8000'.split(':')

timee=time.time()
print('started')
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((ip, int(port)))
while True:
    with open(dir, 'rb') as f:
        content = f.read()
    print('sending',len(content),'bytes')
    client_socket.sendall(content)
    break

Philosophically, what you are doing is a poor way to echo a desktop image to another computer. There are well-established and highly optimized tools that allow you to do that task.