python用socket实现简易局域网UDP组播屏幕分享

这是局域网组播,所以不能跨网段共享,

如果出现[WinError 10040] 一个在数据报套接字上发送的消息大于内部消息缓冲区或其他一些网络限制,或该用户用于接收数据报的缓冲区比数据报小。请将发送端的19行20行(//2)改大,或者将29行quality=50改小

发送方

import socket
import time
import win32api, win32con
from PIL import ImageGrab
from io import BytesIO


# 发送方
def Sender():
    group_ip = '239.0.0.1'
    group_port = 10000
    # 创建IPv4/UDP套接字
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 获取当前分辨率下的屏幕尺寸
    width = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
    height = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
    # 压缩时,大小变为一半
    w = width // 2
    h = height // 2
    while True:
        # 截屏 bbox=None表示截取全屏
        # img = ImageGrab.grab(bbox=None)
        img = ImageGrab.grab(bbox=(0, 0, width, height))
        img.thumbnail((w, h))
        # 图像压缩
        output_buffer = BytesIO()  # 建立二进制对象,在内存中读写
        # RGB格式压缩为JPEG格 式,quality: 保存图像的质量,1(最差)~100
        img.save(output_buffer, format='JPEG', quality=50)
        frame = output_buffer.getvalue()  # 获取二进制数据
        # 发送文件
        sock.sendto(frame, (group_ip, group_port))
        time.sleep(0.05)  # 加点延时更稳定。


if __name__ == "__main__":
    Sender()

接收方

import socket
import struct
import matplotlib.pyplot as plt
import matplotlib.image as image
from io import BytesIO


# 接收方
def Receiver():
    group_ip = '239.0.0.1'  # 组地址
    group_port = 10000  # 端口号
    # 创建IPv4/UDP套接字
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 获取本地ip 先获取主机名,在通过主机名获取ip
    local_ip = socket.gethostbyname(socket.gethostname())
    # 绑定端口
    sock.bind((local_ip, group_port))
    # socket.inet_aton  ip转为二进制
    # socket.INADDR_ANY 所有地址
    mreq = struct.pack("=4sl", socket.inet_aton(group_ip), socket.INADDR_ANY)
    # 加入组播组
    # 使用默认的IPV4组播接口
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
    while True:
        plt.clf()  # 清除上一幅图像
        data, addr = sock.recvfrom(65536)  # 接受数值大一点,防止被撑爆
        img = BytesIO(data)
        img = image.imread(img, format='jpeg')
        plt.imshow(img)
        plt.pause(0.05)  # 暂停0.05秒 这一句是实现动态更新的
        plt.ioff()  # 关闭画图的窗口


if __name__ == '__main__':
    Receiver()

演示:

简易屏幕共享演示

你可能感兴趣的:(python,udp,开发语言,socket,组播)