Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中的屏幕共享_Python_Sockets_Pygame_Screenshot_Screensharing - Fatal编程技术网

python中的屏幕共享

python中的屏幕共享,python,sockets,pygame,screenshot,screensharing,Python,Sockets,Pygame,Screenshot,Screensharing,嗨,我被卡住了,我在网上找不到任何有用的东西。 我正在尝试用python制作一个屏幕共享程序。 问题是我不能以至少24 fps的速度发送屏幕,因为当我用PIL(ImageGrab)截图时,有些东西会延迟。 我的客户将从服务器获取图片(屏幕截图)并“blit”到 屏幕使用pygame 服务器: # -*- coding: utf-8 -*- import socket import os import threading from PIL import ImageGrab def RetrFi

嗨,我被卡住了,我在网上找不到任何有用的东西。 我正在尝试用python制作一个屏幕共享程序。 问题是我不能以至少24 fps的速度发送屏幕,因为当我用PIL(ImageGrab)截图时,有些东西会延迟。 我的客户将从服务器获取图片(屏幕截图)并“blit”到 屏幕使用pygame

服务器:

# -*- coding: utf-8 -*-


import socket
import os
import threading
from PIL import ImageGrab
def RetrFile(name, sock):

    while 1:
        img = ImageGrab.grab()
        img.save("PATH_TO_PIC")

        filename = "PATH_TO_PIC"
        sock.send(str(os.path.getsize(filename)))
        with open('PATH_TO_PIC', 'rb') as f:
            bytesToSend = f.read(1024)
            sock.send(bytesToSend)
            while bytesToSend != "":
                bytesToSend = f.read(1024)
                sock.send(bytesToSend)

def Main():
   host = '0.0.0.0'
   port = 5000

   s = socket.socket()
   s.bind((host,port))

   s.listen(5)
   print "Server Started."

   while True:
       c, addr = s.accept()
       print "Client connected ip: <"+ str(addr) + ">"
       t = threading.Thread(target = RetrFile, args = ("retrThread", c))
       t.start()
   s.close()

if __name__ == '__main__':
    Main()
#-*-编码:utf-8-*-
导入套接字
导入操作系统
导入线程
从PIL导入ImageGrab
def RetrFile(名称、sock):
而1:
img=ImageGrab.grab()
图像保存(“路径到图片”)
filename=“路径到图片”
send(str(os.path.getsize(文件名)))
以open('PATH_TO_PIC','rb')作为f:
bytesToSend=f.read(1024)
sock.send(bytesToSend)
而bytesToSend!="":
bytesToSend=f.read(1024)
sock.send(bytesToSend)
def Main():
主机='0.0.0.0'
端口=5000
s=socket.socket()
s、 绑定((主机、端口))
s、 听(5)
打印“服务器已启动”
尽管如此:
c、 addr=s.accept()
打印“客户端连接的ip:”
线程(target=RetrFile,args=(“retrThread”,c))
t、 开始()
s、 关闭()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
Main()
客户:

import socket
import pygame as pg
def Main():
    host = '127.0.0.1'
    port = 5000


    pg.init()
    display_screen = pg.display.set_mode((1900, 1000))



    clock = pg.time.Clock()

    s = socket.socket()
    s.connect((host,port))
    filename =  "PATH_TO_PIC"
    isExit = False
    while not isExit:

        for event in pg.event.get():
            if event.type == pg.QUIT:
                isExit = True
        data = s.recv(1024)
        print data
        filesize = long(data)

        f = open(filename, 'wb')
        data = s.recv(1024)
        totalRecv  =  len(data)
        f.write(data)
        while totalRecv < filesize:
            data = s.recv(1024)
            totalRecv += len(data)
            f.write(data)
        showImg = pg.image.load('PATH_TO_PIC')
        display_screen.blit(showImg, (0,0))
        pg.display.flip()
        clock.tick(60)
    s.close()

if __name__ == '__main__':
    Main()
导入套接字
导入pygame作为pg
def Main():
主机='127.0.0.1'
端口=5000
第init页()
显示屏幕=pg.display.set_模式((1900,1000))
时钟=pg.time.clock()
s=socket.socket()
s、 连接((主机、端口))
filename=“路径到图片”
isExit=False
虽然不是isExit:
对于pg.event.get()中的事件:
如果event.type==pg.QUIT:
isExit=True
数据=s.recv(1024)
打印数据
filesize=long(数据)
f=打开(文件名“wb”)
数据=s.recv(1024)
totalRecv=len(数据)
f、 写入(数据)
totalRecv<文件大小:
数据=s.recv(1024)
totalRecv+=len(数据)
f、 写入(数据)
showImg=pg.image.load('PATH\u TO\u PIC')
显示屏幕blit(显示(0,0))
pg.display.flip()
时钟滴答(60)
s、 关闭()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
Main()
基本上,我的问题是:如何在两台计算机之间共享一个屏幕,我不知道使用PIL发送大量图片的方式是否有效和正确。
有没有更有效的方法?这会投射1号计算机的屏幕,并在2号计算机上显示它?

我刚刚尝试过,它似乎运行得很好(Python 3)。如果您认为这可以接受,请告诉我,我正在使用MSS模块来防止I/O

server.py

from socket import socket
from threading import Thread
from zlib import compress

from mss import mss


WIDTH = 1900
HEIGHT = 1000


def retreive_screenshot(conn):
    with mss() as sct:
        # The region to capture
        rect = {'top': 0, 'left': 0, 'width': WIDTH, 'height': HEIGHT}

        while 'recording':
            # Capture the screen
            img = sct.grab(rect)
            # Tweak the compression level here (0-9)
            pixels = compress(img.rgb, 6)

            # Send the size of the pixels length
            size = len(pixels)
            size_len = (size.bit_length() + 7) // 8
            conn.send(bytes([size_len]))

            # Send the actual pixels length
            size_bytes = size.to_bytes(size_len, 'big')
            conn.send(size_bytes)

            # Send pixels
            conn.sendall(pixels)


def main(host='0.0.0.0', port=5000):
    sock = socket()
    sock.connect((host, port))
    try:
        sock.listen(5)
        print('Server started.')

        while 'connected':
            conn, addr = sock.accept()
            print('Client connected IP:', addr)
            thread = Thread(target=retreive_screenshot, args=(conn,))
            thread.start()
    finally:
        sock.close()


if __name__ == '__main__':
    main()
from socket import socket
from zlib import decompress

import pygame

WIDTH = 1900
HEIGHT = 1000


def recvall(conn, length):
    """ Retreive all pixels. """

    buf = b''
    while len(buf) < length:
        data = conn.recv(length - len(buf))
        if not data:
            return data
        buf += data
    return buf


def main(host='127.0.0.1', port=5000):
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    clock = pygame.time.Clock()
    watching = True    

    sock = socket()
    sock.connect((host, port))
    try:
        while watching:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    watching = False
                    break

            # Retreive the size of the pixels length, the pixels length and pixels
            size_len = int.from_bytes(sock.recv(1), byteorder='big')
            size = int.from_bytes(sock.recv(size_len), byteorder='big')
            pixels = decompress(recvall(sock, size))

            # Create the Surface from raw pixels
            img = pygame.image.fromstring(pixels, (WIDTH, HEIGHT), 'RGB')

            # Display the picture
            screen.blit(img, (0, 0))
            pygame.display.flip()
            clock.tick(60)
    finally:
        sock.close()


if __name__ == '__main__':
    main()
client.py

from socket import socket
from threading import Thread
from zlib import compress

from mss import mss


WIDTH = 1900
HEIGHT = 1000


def retreive_screenshot(conn):
    with mss() as sct:
        # The region to capture
        rect = {'top': 0, 'left': 0, 'width': WIDTH, 'height': HEIGHT}

        while 'recording':
            # Capture the screen
            img = sct.grab(rect)
            # Tweak the compression level here (0-9)
            pixels = compress(img.rgb, 6)

            # Send the size of the pixels length
            size = len(pixels)
            size_len = (size.bit_length() + 7) // 8
            conn.send(bytes([size_len]))

            # Send the actual pixels length
            size_bytes = size.to_bytes(size_len, 'big')
            conn.send(size_bytes)

            # Send pixels
            conn.sendall(pixels)


def main(host='0.0.0.0', port=5000):
    sock = socket()
    sock.connect((host, port))
    try:
        sock.listen(5)
        print('Server started.')

        while 'connected':
            conn, addr = sock.accept()
            print('Client connected IP:', addr)
            thread = Thread(target=retreive_screenshot, args=(conn,))
            thread.start()
    finally:
        sock.close()


if __name__ == '__main__':
    main()
from socket import socket
from zlib import decompress

import pygame

WIDTH = 1900
HEIGHT = 1000


def recvall(conn, length):
    """ Retreive all pixels. """

    buf = b''
    while len(buf) < length:
        data = conn.recv(length - len(buf))
        if not data:
            return data
        buf += data
    return buf


def main(host='127.0.0.1', port=5000):
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    clock = pygame.time.Clock()
    watching = True    

    sock = socket()
    sock.connect((host, port))
    try:
        while watching:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    watching = False
                    break

            # Retreive the size of the pixels length, the pixels length and pixels
            size_len = int.from_bytes(sock.recv(1), byteorder='big')
            size = int.from_bytes(sock.recv(size_len), byteorder='big')
            pixels = decompress(recvall(sock, size))

            # Create the Surface from raw pixels
            img = pygame.image.fromstring(pixels, (WIDTH, HEIGHT), 'RGB')

            # Display the picture
            screen.blit(img, (0, 0))
            pygame.display.flip()
            clock.tick(60)
    finally:
        sock.close()


if __name__ == '__main__':
    main()
从套接字导入套接字
从zlib导入解压缩
导入pygame
宽度=1900
高度=1000
def recvall(连接,长度):
“”“检索所有像素。”“”
buf=b''
而len(buf)<长度:
数据=conn.recv(长度-长度(buf))
如果没有数据:
返回数据
buf+=数据
返回buf
def干管(主机=127.0.0.1',端口=5000):
pygame.init()
screen=pygame.display.set_模式((宽度、高度))
clock=pygame.time.clock()
观看=真实
sock=socket()
sock.connect((主机、端口))
尝试:
观看时:
对于pygame.event.get()中的事件:
如果event.type==pygame.QUIT:
监视=错误
打破
#检索像素长度、像素长度和像素的大小
size\u len=int.from\u字节(sock.recv(1),byteorder='big')
size=int.from_字节(sock.recv(size_len),byteorder='big')
像素=解压缩(recvall(sock,size))
#从原始像素创建曲面
img=pygame.image.fromstring(像素,(宽度,高度),'RGB')
#显示图片
屏幕blit(img,(0,0))
pygame.display.flip()
时钟滴答(60)
最后:
sock.close()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()

您可以通过使用另一种压缩算法(如LZ4)进行改进,该算法具有Python实现。您需要尝试:)

对@Tiger-222的代码进行以下更改

size\u len=int.from\u字节(sock.recv(1),byteorder='big')
size=int.from_字节(recvall(sock,size_len),byteorder='big')

我制作了一个反向屏幕广播(一个测试工具), 服务器(受害者)将数据发送到客户端(攻击者)的位置

攻击者

import socket
from zlib import decompress

import pygame

WIDTH = 1900
HEIGHT = 1000


def recvall(conn, length):
    """ Retreive all pixels. """
    buf = b''
    while len(buf) < length:
        data = conn.recv(length - len(buf))
        if not data:
            return data
        buf += data
    return buf

def main(host='192.168.1.208', port=6969):
    ''' machine lhost'''
    sock = socket.socket()
    sock.bind((host, port))
    print("Listening ....")
    sock.listen(5)
    conn, addr = sock.accept()
    print("Accepted ....", addr)

    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    clock = pygame.time.Clock()
    watching = True    

    
    try:
        while watching:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    watching = False
                    break

            # Retreive the size of the pixels length, the pixels length and pixels
            size_len = int.from_bytes(conn.recv(1), byteorder='big')
            size = int.from_bytes(conn.recv(size_len), byteorder='big')
            pixels = decompress(recvall(conn, size))

            # Create the Surface from raw pixels
            img = pygame.image.fromstring(pixels, (WIDTH, HEIGHT), 'RGB')

            # Display the picture
            screen.blit(img, (0, 0))
            pygame.display.flip()
            clock.tick(60)
    finally:
        print("PIXELS: ", pixels)
        sock.close()

if __name__ == "__main__":
    main()  
对于服务器:

import socket
from zlib import decompress

import pygame

WIDTH = 1900
HEIGHT = 1000


def recvall(conn, length):
    """ Retreive all pixels. """
    buf = b''
    while len(buf) < length:
        data = conn.recv(length - len(buf))
        if not data:
            return data
        buf += data
    return buf


def main(host='0.0.0.0', port=6969):
    ''' machine lhost'''
    sock = socket.socket()
    sock.bind((host, port))
    print("Listening ....")
    sock.listen(5)
    conn, addr = sock.accept()
    print("Accepted ....", addr)

    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    clock = pygame.time.Clock()
    watching = True

    try:
        while watching:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    watching = False
                    break

            # Retreive the size of the pixels length, the pixels length and pixels
            size_len = int.from_bytes(conn.recv(1), byteorder='big')
            size = int.from_bytes(conn.recv(size_len), byteorder='big')
            pixels = decompress(recvall(conn, size))

            # Create the Surface from raw pixels
            img = pygame.image.fromstring(pixels, (WIDTH, HEIGHT), 'RGB')

            # Display the picture
            screen.blit(img, (0, 0))
            pygame.display.flip()
            clock.tick(60)
    finally:
        print("PIXELS: ", pixels)
        sock.close()


if __name__ == "__main__":
    main()

我对基于python的屏幕共享脚本集很感兴趣。我不想编写低级套接字代码。我最近发现了一个有趣的消息代理/服务器,名为mosquitto()。简而言之,您可以连接到服务器并订阅主题。当代理收到关于您订阅的主题的消息时,它将向您发送该消息

下面是两个连接到mosquitto代理的脚本。一个脚本侦听屏幕抓取请求。另一个脚本请求屏幕抓取并显示它们

这些脚本依靠图像处理模块来完成繁重的工作 过程是

  • 客户端请求屏幕
  • 服务器被通知有一条关于屏幕抓取主题的消息
  • 服务器用mss抓取屏幕
  • 服务器将屏幕转换为numpy
  • server base 64对压缩的pickled numpy映像进行编码
  • 如果可能,服务器会对最后一个映像执行增量
  • 服务器将base 64字符串发布到屏幕抓取主题
  • 通知客户端屏幕抓取主题上有一条消息
  • 客户端反转该过程
  • 客户端显示屏幕
  • 客户端返回到步骤1
  • 使用命令行消息退出服务器 C:\Program Files\mosquitto>mosquitto_pub.exe-h“127.0.0.1”-t“服务器/退出”-m“0”

    此实现使用增量刷新。它使用numpy到xo
    import paho.mqtt.client as mqtt
    import time
    import uuid
    import cv2
    import mss
    from mss.tools import zlib
    import numpy
    import base64
    import io
    import pickle
    
    monitor = 0 # all monitors
    quit = False
    capture = False
    
    def on_connect(client, userdata, flags, rc):
        print("Connected flags " + str(flags) + " ,result code=" + str(rc))
    
    def on_disconnect(client, userdata, flags, rc):
        print("Disconnected flags " + str(flags) + " ,result code=" + str(rc))
    
    def on_message(client, userdata, message):
        global quit
        global capture
        global last_image
    
        if message.topic == "server/size":
            with mss.mss() as sct:
                sct_img = sct.grab(sct.monitors[monitor])
                size = sct_img.size
                client.publish("client/size", str(size.width) + "|" + str(size.height))
    
        if message.topic == "server/update/first":
            with mss.mss() as sct:
                b64img = BuildPayload(False)
                client.publish("client/update/first", b64img)
    
        if message.topic == "server/update/next":
            with mss.mss() as sct:
                b64img = BuildPayload()
                client.publish("client/update/next", b64img)
    
        if message.topic == "server/quit":
            quit = True
    
    def BuildPayload(NextFrame = True):
        global last_image
        with mss.mss() as sct:
            sct_img = sct.grab(sct.monitors[monitor])
            image = numpy.array(sct_img)
            if NextFrame  == True:
                # subsequent image - delta that brings much better compression ratio as unchanged RGBA quads will XOR to 0,0,0,0
                xor_image = image ^ last_image
                b64img = base64.b64encode(zlib.compress(pickle.dumps(xor_image), 9))
            else:
                # first image - less compression than delta
                b64img = base64.b64encode(zlib.compress(pickle.dumps(image), 9))
                print("Source Image Size=" + str(len(sct_img.rgb)))
            last_image = image
            print("Compressed Image Size=" + str(len(b64img)) + " bytes")
            return b64img
    
    myid = str(uuid.uuid4()) + str(time.time())
    print("Client Id = " + myid)
    client = mqtt.Client(myid, False)
    client.on_connect = on_connect
    client.on_disconnect = on_disconnect
    client.on_message = on_message
    try:
        client.connect("127.0.0.1")
        client.loop_start()
        client.subscribe("server/size")
        client.subscribe("server/update/first")
        client.subscribe("server/update/next")
        client.subscribe("server/quit")
        while not quit:
            time.sleep(5)
            continue
        client.publish("client/quit")
        time.sleep(5)
        client.loop_stop()
        client.disconnect()
    except:
        print("Could not connect to the Mosquito server")
    
    
    import paho.mqtt.client as mqtt
    import time
    import uuid
    import cv2
    import mss
    from mss.tools import zlib
    import numpy
    import base64
    import io
    import pickle
    
    quit = False
    size = False
    capture = False
    width = 0
    height = 0
    last_image = None
    first = False
    
    def on_connect(client, userdata, flags, rc):
        print("Connected flags " + str(flags) + " ,result code=" + str(rc))
    
    def on_message(client, userdata, message):
        global quit
        global size
        global capture
        global width
        global height
        global last_image
        global first
    
        if message.topic == "client/size":
            if width == 0 and height == 0:
                strsize = message.payload.decode("utf-8")
                strlist = strsize.split("|")
                width = int(strlist[0])
                height = int(strlist[1])
                size = True
    
        if message.topic == "client/update/first":
            # stay synchronized with other connected clients
            if size == True:
                DecodeAndShowPayload(message, False)
                first = True
    
        if message.topic == "client/update/next":
            # stay synchronized with other connected clients
            if size == True and first == True: 
                DecodeAndShowPayload(message)
    
        if message.topic == "client/quit":
            quit = True
    
    def DecodeAndShowPayload(message, NextFrame = True):
        global last_image
        global capture
        global quit
    
        if NextFrame == True:
            # subsequent image - delta that brings much better compression ratio as unchanged RGBA quads will XOR to 0,0,0,0
            xor_image = pickle.loads(zlib.decompress(base64.b64decode(message.payload.decode("utf-8")), 15, 65535))
            image = last_image ^ xor_image
        else:
            # first image - less compression than delta
            image = pickle.loads(zlib.decompress(base64.b64decode(message.payload.decode("utf-8")), 15, 65535))
        last_image = image
        cv2.imshow("Server", image)
        if cv2.waitKeyEx(25) == 113:
            quit = True
        capture = False
    
    myid = str(uuid.uuid4()) + str(time.time())
    print("Client Id = " + myid)
    client = mqtt.Client(myid, False)
    client.on_connect = on_connect
    client.on_message = on_message
    try:
        client.connect("127.0.0.1")
        client.loop_start()
        client.subscribe("client/size")
        client.subscribe("client/update/first")
        client.subscribe("client/update/next")
        client.subscribe("client/quit")
    
        # ask once and retain in case client starts before server
        asksize = False
        while not size:
            if not asksize:
                client.publish("server/size", "1", 0, True)
                asksize = True 
            time.sleep(1)
    
        first_image = True
        while not quit:
            if capture == False:
                capture = True
                if first_image:
                    client.publish("server/update/first")
                    first_image = False
                else:
                    client.publish("server/update/next")
            time.sleep(.1)
    
        cv2.destroyAllWindows()
        client.loop_stop()
        client.disconnect()
    except:
        print("Could not connect to the Mosquito server")