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,不想一点一点敲链接,又苦于没有找到其它好的方 ...
随机推荐
- VMX指令集
指令 作用 VMPTRLD 加载一个VMCS结构体指针作为当前操作对象 VMPTRST 保存当前VMCS结构体指针 VMCLEAR 清除当前VMCS结构体 VMREAD 读VMCS结构体指定域 VMW ...
- Entity Framework 6.1.2 offset row fetch next 错误解决办法
本地测试环境用的SqlServer2012,生产环境2008R2.然后在查询分页数据时生产环境悲剧的报错了. 原因是EF6.1.2以上版本在编译SQL时使用了新的语法对低版本的SqlServer不兼容 ...
- 【乱入】Uva11021麻球繁衍
就是根据概率公式入门算算. #include<bits/stdc++.h> ; int n,m,k; double p[N],f[N]; int main(){ int T;scanf(& ...
- 存储过程 ----- navicat 创建存储过程
以下为navicat 创建存储过程步骤图解: 1. 2. 3. 4. 在存储过程正文中是输入一行语句测试用,点击保存 5.输入存储过程名称,点击确定 6.到这来那么问题来了,会提示错误 7.切记存储过 ...
- MATLAB规划问题——线性规划和非线性规划
1.线性规划 求线性规划问题的最优解有两种方法,一种方法是使用linprog命令,另一种是使用optimtool工具箱,下面分别介绍这两种方法. ①linprog命令 一般情况下,Linprog命令的 ...
- iOS运行时,如何增加成员变量
必须实现getter和setter方法 ``` - (void)setName:(NSString *)name { /** * 为某个类关联某个对象 * * @param object#> 要 ...
- php(间接)调用nmap命令时的选项特殊点
使用php调用pythn-nmap时,发现无法正常执行扫描动作 将nmap命令直接写入php,由后者调用,发现仍然无法执行,提示需要添加“-Pn”选项 原来是: 正常情况下:nmap -n host ...
- 内部网络出口防火墙导致TCP类扫描异常
测试过程中确认,由于内部网络出口防火墙存在连接数等策略限制,会导致TCP类扫描出现异常,表现为大量误报. Nessus.nmap.synscan均存在此现象.
- HTTP.SYS
严格地说,HTTP.SYS已经不属于IIS 的范畴了,所以HTTP.SYS的配置信息也没有保存在IIS 的元数据库(Metabase) 中,而是定义在注册表中.HTTP.SYS 的注册表项的路径为HK ...
- gcc与gdb的使用
1.gcc/g++编译过程: gcc/g++的编译格式: gcc [option][filename]... g++ [option][filename]... 1)processing:预处理过程, ...