我无法发送图片(socket 和 ngrok)

0 投票
1 回答
41 浏览
提问于 2025-04-14 17:30

客户端:

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()

服务器:

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()

在传输过程中,图片被中断了。我该怎么解决这个问题呢?

图片没有完全传输过来。ngrok似乎在干扰这个图片的传输。也许还有其他合适的方法可以打开端口?

在没有进行base64解码的情况下传输图片,图片也会出现问题。

1 个回答

1

这段话是关于解决你在使用socket时遇到的问题的。作者修改了服务器的代码,让它在“读取”数据时一直循环,直到返回0,这个0表示socket已经关闭。这样做的好处是可以接收到完整的图像。同时,作者在两个循环中添加了break,这样就不会无限循环下去了。此外,作者还去掉了tkinter的部分,以免让问题变得更加复杂。

需要注意的是,你把“服务器”和“客户端”搞反了。执行“accept”的是服务器,而执行“connect”的是客户端。作者还去掉了ImageGrab,因为在Linux的Wayland环境下这个功能是无法使用的。

服务器代码:

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()

客户端代码:

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

从哲学上讲,你现在的做法并不是一个好的方法来将桌面图像传输到另一台计算机上。其实有一些已经成熟且经过高度优化的工具,可以更好地完成这个任务。

撰写回答