Python实现局域网内屏幕广播的技术要点分析(转载)
为更好地保证教学质量和提高学生的学习积极性,我使用Python开发了一套课堂教学管理系统,具有在线点名、在线答疑、随机提问、在线作业管理、在线自测、在线考试、数据汇总、试卷生成、屏幕广播等功能,教师端运行界面如下图所示:
该系统投入使用已有4个学期,效果非常好,不仅可以满足上课的各种需要,还可以作为“Python程序设计”课程的一个完整教学案例讲给学生,适用教材包括《Python程序设计基础》(董付国编著,清华大学出版社)、《Python程序设计(第2版)》(董付国
编著,清华大学出版社)、《Python可以这样学》(董付国著,清华大学出版社)。本文重点介绍屏幕广播功能的技术要点,本系统界面使用tkinter编写,使用扩展库pillow实现屏幕截图,使用socket实现屏幕截图的传送,使用多线程技术实现多客户端的数据传
输,文中略去了有关标准库和扩展库的导入代码。
1、学生端启动之后,监听UDP端口1000,等待教师端发送屏幕广播指令,代码如下:
def udpListen(): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 监听本机10000端口 sock.bind(('',10000)) while True: data, addr = sock.recvfrom(100) # 收到服务器发来的广播指令 if data == b'startBroadCast': threading.Thread(target=receiveBroadCast).start() sock.close() threading.Thread(target=udpListen).start()
2、教师端通过界面上的按钮“开始屏幕广播”给局域网内所有学生端发送指令,同时监听TCP端口10001,等待学生端的连接,然后给每一个学生端连接发送本机屏幕截图,每0.5秒刷新一次。代码如下:
broadcasting = False def broadcast(conn): global broadcasting while broadcasting: time.sleep(0.8) image = ImageGrab.grab() size = image.size imageBytes = image.tobytes() length = len(imageBytes) # 通知将要开始发送截图 conn.send(b'*****') fhead = struct.pack('I32sI', length, str(size).encode(), len(str(size).encode())) conn.send(fhead) conn.send(imageBytes) else: conn.send(b'#####') conn.close() def broadcastMain(): '''广播屏幕截图的主线程函数''' global sockBroadCast sockBroadCast = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sockBroadCast.bind(('', 10001)) sockBroadCast.listen(150) while broadcasting: try: conn, addr = sockBroadCast.accept() except: return threading.Thread(target=broadcast, args=(conn,)).start() else: sockBroadCast.close() def onbuttonStartBroadCastClick(): global broadcasting broadcasting = True # 启动服务器广播线程 threading.Thread(target=broadcastMain).start() # 通知客户端开始接收广播 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) IP = socket.gethostbyname(socket.gethostname()) IP = IP[:IP.rindex('.')]+'.255' sock.sendto(b'startBroadCast', (IP, 10000)) buttonStopBroadCast['state'] = 'normal' buttonStartBroadCast['state'] = 'disabled' buttonStartBroadCast = tkinter.Button(root, text='开始屏幕广播', command=onbuttonStartBroadCastClick) buttonStartBroadCast.place(x=20, y=380, width=100, height=30) def onbuttonStopBroadCastClick(): global broadcasting broadcasting = False sockBroadCast.close() buttonStopBroadCast['state'] = 'disabled' buttonStartBroadCast['state'] = 'normal' buttonStopBroadCast = tkinter.Button(root, text='结束屏幕广播', command=onbuttonStopBroadCastClick) buttonStopBroadCast['state'] = 'disabled' buttonStopBroadCast.place(x=130, y=380, width=100, height=30)
3、学生端收到教师端通过UDP广播发送的屏幕广播指令之后,创建TCP Socket,连接教师端,并接收教师端发来的屏幕截图,然后使用创建顶端显示的tkinter界面用来显示屏幕截图。主要功能代码如下:
# 使用TCP接收广播 def receiveBroadCast(): # 获取屏幕尺寸,创建顶端显示的无标题栏窗体 screenWidth = 640 screenHeight = 480 top = tkinter.Toplevel(root, width=screenWidth, height=screenHeight) top.overrideredirect(True) # 顶端显示 top.attributes('-topmost', 1) # 创建画布,用来显示图像 canvas = tkinter.Canvas(top, bg='white', width=screenWidth, height=screenHeight) canvas.pack(fill=tkinter.BOTH, expand=tkinter.YES) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serverIP = entryServerIP.get() # 连接服务器10001端口,失败直接返回 try: sock.connect((serverIP, 10001)) except: print('error') top.destroy() return # 接收服务器指令 # *****表示开始传输一个新的截图 # #####表示本次广播结束 while True: data = sock.recv(5) if data == b'*****': # 接收服务器发来的一屏图像 # 图像大小,字节总数量 len_head = struct.calcsize('I32sI') data = sock.recv(len_head) length, size, sizeLength = struct.unpack('I32sI', data) length = int(length) size = eval(size[:int(sizeLength)]) rest = length image = [] while True: if rest == 0: break elif rest > 40960: temp = sock.recv(40960) rest -= len(temp) image.append(temp) else: temp = sock.recv(rest) rest -= len(temp) image.append(temp) image = b''.join(image) # 更新显示 image = Image.frombytes('RGB', size, image) image = image.resize((screenWidth, screenHeight)) image = ImageTk.PhotoImage(image) try: canvas.delete(imageId) except: pass imageId = canvas.create_image(screenWidth//2, screenHeight//2, image=image) elif data == b'#####': # 广播结束 break # 本次广播结束,关闭窗口 sock.close() top.destroy()
Python实现局域网内屏幕广播的技术要点分析(转载)的更多相关文章
- 混合事务分析处理“HTAP”的技术要点分析
HTAP是近些年来比较火的一个概念,本文将聊聊HTAP的前世今生及技术特点. 一.数据应用类别 根据数据的使用特征,可简单做如下划分.在选择技术平台之前,我们需要做好这样的定位. 1.1 OLTP 联 ...
- 使用 Python 查看局域网内存活主机
1 安装 (如果误用了 pip insatll nmap的话,要先 pip uninstall nmap) pip install python-nmap Nmap 是一款用于网络发现和安全审计的网络 ...
- 使用Python检测局域网内IP地址使用情况
来源:https://www.cnblogs.com/donlin-zhang/p/6812675.html 在测试环境搭建的过程中,经常需要给服务器分配静态IP地址,由于不清楚当前局域网内部哪些IP ...
- Mysql 锁技术要点【转载】
MyISAM和InnoDB的区别 MySQL默认采用的是MyISAM. MyISAM不支持事务,而InnoDB支持.InnoDB的AUTOCOMMIT默认是打开的,即每条SQL语句会默认被封装成一个事 ...
- 可以搜索局域网内的所有IP地址的软件
几乎都用现有的工具,直接扫描,这里我已python为例,搜索一下局域网内所有活动IP,基本原理就是ping,对返回的结果进行分析,从而判断对应ip是否活动,代码很简单,实验环境win10+python ...
- Python一个命令开启http下载服务器(可以局域网内共享文件)
前提条件:windows系统上安装python 如果想把D:\asdm作为提供下载的目录, 打开cmd然后cd命令进入该目录:cd D:\asdm, 然后执行Python -m SimpleHTTPS ...
- ICMP协议 广播以查询局域网内的所有主机
看到了很多局域网内的主机扫描工具,在想怎么去实现这样一个工具.前几天看了Ping源码--ICMP协议的实例,ICMP可以用来探测网联网内的任一主机,ICMP和广播地址结合来扫描局域网内的所有主机不是很 ...
- wifi智能插座 一键扫描局域网内插座Ip及其它信息 Python源代码API
转载请保留原地址. http://www.cnblogs.com/lsqandzy 最近买了几个智能插座玩,插座安装在家里,连接好wifi,不管你人在哪里,通过手机,一键开启或关闭插座电源,想象一下, ...
- 局域网内python socket实现windows与linux间简单的消息传送
有个需求,就是在windows上看见一篇介绍linux相关的文章,想在局域网内的另外一台linux电脑上尝试一下, 于是就需要把该网页链接发送给linux,不想一点一点敲链接,又苦于没有找到其它好的方 ...
随机推荐
- Flex slider使用方法
1.首先在页面head部位载入jquery库文件和Flexslider插件,以及Flexslider所需的基本css样式文件. <link rel="stylesheet" ...
- 转载:document.execCommand()的用法小记
首先要说明的是在firefox下支持不好.2D-Position 允许通过拖曳移动绝对定位的对象. AbsolutePosition 设定元素的 position 属性为“absolute”(绝对). ...
- python中deque类详解
最近在pythonTip做题的时候,遇到了deque类,以前对其不太了解,现在特此总结一下 deque类是python标准库collections模块中的一项,它提供了两端都可以操作的序列,这意味着, ...
- Net Core 控制台程序使用Nlog 输出到log文件
using CoreImportDataApp.Common; using Microsoft.Extensions.Configuration; using Microsoft.Extensions ...
- k8s的Health Check(健康检查)
强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性.自愈的默认实现方式是自动重启发生故障的容器.除此之外,用户还可以利用 Liveness 和 Readiness 探测机制设置更精 ...
- poj 3254(状态压缩+动态规划)
http://poj.org/problem?id=3254 题意:有一个n*m的农场(01矩阵),其中1表示种了草可以放牛,0表示没种草不能放牛,并且如果某个地方放了牛,它的上下左右四个方向都不能放 ...
- 图解Javascript——执行上下文
什么是执行上下文? 执行上下文(Execution Context)是ECMAScript规范中用来描述 JavaScript 代码执行的抽象概念,规定了当前代码执行的环境(当前执行代码片段中的变量. ...
- CF 1003C Intense Heat【前缀和/精度/双层暴力枚举】
The heat during the last few days has been really intense. Scientists from all over the Berland stud ...
- Java异常处理机制及两种异常的区别
java异常处理机制主要依赖于try,catch,finally,throw,throws五个关键字. try 关键字后紧跟一个花括号括起来的代码块,简称try块.同理:下面的也被称为相应的块. ...
- POJ 2559 Largest Rectangle in a Histogram(单调栈)
[题目链接] http://poj.org/problem?id=2559 [题目大意] 给出一些宽度为1的长方形下段对其后横向排列得到的图形,现在给你他们的高度, 求里面包含的最大长方形的面积 [题 ...