-----------------------------------------------------------------------------------
-----------------------一、Java项目和包结构如下:-----------------------
-----------------------------------------------------------------------------------
![](https://i-blog.csdnimg.cn/blog_migrate/92f207f1e82cad76451c4d340201b4d6.png)
-----------------------------------------------------------------------------------
-----------------------二、
教师端Main类
:----------------------------------
-----------------------------------------------------------------------------------
public class TeacherMain {
public static void main(String[] args) {
new Teacher().startTeacher();
}
}
-----------------------------------------------------------------------------------
-----------------------三、
教师端
:-------------------------------------------
-----------------------------------------------------------------------------------
public class Teacher {
//机器人类
private Robot robot;
//截屏区域
private Rectangle rect;
public Teacher() {
try {
this.robot = new Robot();
this.rect = new Rectangle(0, 0, 1366, 768);
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//开启UDP 教师端
public void startTeacher()
{
try {
//1.创建udp套接字,并设定发送广播的端口
DatagramSocket tSocket = new DatagramSocket(8888);
//2.创建pack
byte [] buf = new byte[1024 * 60 + 14];
DatagramPacket tPack = new DatagramPacket(buf, buf.length);
//3.设定pack的目的地
tPack.setAddress(InetAddress.getByName("192.168.0.107"));
//4.设定pack的目标端口
tPack.setPort(9999);
//此处开始循环,每次循环时,发送一屏(多块==多UDP包)
while(true)
{
//5.设定pack的内容
//---5.1:捕捉屏幕
BufferedImage bufImg = catchScreen();
//---5.2:压缩并获取屏幕字节数组
byte [] allImgByteArr = zipImgGetBytes(bufImg);
//---5.3:创建分块字节数组列表
List<byte[]> blockList = creatBlockList(allImgByteArr);
System.out.println("bs.length:" + allImgByteArr.length + "---bs.blocks" + blockList.size());
//6.循环发送
for (byte[] bs : blockList) {
//设定数据
tPack.setData(bs);
//发送
tSocket.send(tPack);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 捕获一帧屏幕
*/
private BufferedImage catchScreen() {
return robot.createScreenCapture(rect);
}
/**
* 压缩图片,获取图片字节
*/
private byte [] zipImgGetBytes(BufferedImage bufImg)
{
try {
//创建内存字节流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//创建压缩流
ZipOutputStream zos = new ZipOutputStream(baos);
//设定压缩入口
zos.putNextEntry(new ZipEntry("xxx"));
//将图片写入压缩流
ImageIO.write(bufImg, "jpg", zos);
zos.close();
//获取压缩后图片的字节数组
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取分块字节数组集合
* 拆分字节数组为60K的块,并且添加固定报头
*/
public List<byte[]> creatBlockList(byte[] allImgByteArr)
{
//分块数组集合
List<byte[]> blockList = new ArrayList<byte[]>();
//1.设定标准块大小(包括报头)
int standTotleBlockSize = 60 * 1024 + 14;
//2.设定纯块大小,不含报头 60K
int standBlockSize = 60 * 1024;
//6.剩余字节数(最后一块)
int remain = allImgByteArr.length % standBlockSize;
//5.块数
int blockCount = allImgByteArr.length / standBlockSize;
if(remain != 0)
{
blockCount = allImgByteArr.length / standBlockSize + 1;
}
//设定读写缓冲区
byte [] bs;
//7.开始分块(组装报文)
//1.获取并写入唯一标识
long flag = System.currentTimeMillis();
for (int i = 0; i < blockCount; i++) {
//7.设定当前分块字节数组,含报头(因为有最后一块不足的问题)
byte [] curTotleByteArr = new byte[standTotleBlockSize];
//8.设定当前分块字节数组,纯内容不含报头(因为有最后一块不足的问题)
byte [] curByteArr = new byte[standBlockSize];
//如果是最后一块,而且余数不为0,说明最后一块不足60K
if(remain != 0 && i == (blockCount - 1))
{
curTotleByteArr = new byte[remain + 14];
curByteArr = new byte[remain];
}
bs = Util.long2Bytes(flag);
System.arraycopy(bs, 0, curTotleByteArr, 0, 8);
//2.写入总块数
curTotleByteArr[8] = (byte)blockCount;
System.out.println("New Msg flag:" + flag + "totle count" + curTotleByteArr[8]);
//3.写入当前块序号
curTotleByteArr[9] = (byte)i;
//4.写入内容长度
bs = Util.int2Bytes(curByteArr.length);
System.arraycopy(bs, 0, curTotleByteArr, 10, 4);
//5.写入内容
System.arraycopy(allImgByteArr, i * standBlockSize, curTotleByteArr, 14, curByteArr.length);
//6.添加掉数组
//System.out.println("");
blockList.add(curTotleByteArr);
}
return blockList;
}
}