一、主要技术--按照客户端控制服务器的实现来讲
UDP版和TCP版的主要区别是数据发送方式不同,tcp通过连接,通过流来发送和接受数据,非常可靠,UDP是
发送数据包和接受数据包的过程,而且发送的数据包可能丢失,数据包的大小也有限制。也就是字节数组的大小有限制。
我的屏幕截图下来有4M,不能够一次性发在字节数组中发送,我的实现办法是,先将对象序列化写入文件,然后将文件分成一百分发送出去,客户端接受的时候也将接收的字节写入文件,然后用对象输入流读取,就相当于对象的序列化过程,和文件复制。
二、主要实现步奏都是一样的可以参考tcp的实现,下面是发送数据和接受数据的过程。
1、服务器发送数据包代码
注意事项,由于可能丢包,所以每发送一张图片也就是一个对象时,先发送”开始标记“,然后再发送分隔的100分字节数组,客户端在接收到”开始“字节数组之后开始接受,接受100份后边开始按照对象流读取图片对象,如果对象读取不成功,说明这100份字节数组出现了错误,不是一个完整的对象的字节数组,将其丢弃重新开始接受,直到对象成功读取才将去画在客户端的面板上。
public void run() {
Robot robot;
try {
robot = new Robot();
while (true) {
System.out.println("开始");
//得到屏幕大小,由于在远程控制中,可能改变屏幕分辨率,所以要不断获取
Toolkit tool = Toolkit.getDefaultToolkit();
//
Dimension dimension= tool.getScreenSize();
Point point = new Point(0,0);
//创建一个矩形用于指定截屏区域
Rectangle screenRect = new Rectangle(point,dimension);
// 不断地截屏,然后发给客户端
BufferedImage bimg = robot.createScreenCapture(screenRect);
//BufferedImage没有实现接口,所以不能被实例化,所以将其转成imageicon
ImageIcon img = new ImageIcon(bimg);
//*********************************************************************** 、
//先把对象写入文件,再把文件转成字节数组发出去,对方接受文件,再按对象读取
File file = new File("d:/jietu.png");
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//包装成对象流
ObjectOutputStream os = new ObjectOutputStream(bos);
//将对象写入文件
os.writeObject(img);
os.flush();
//*******************
//将文件转成字节流发出去
byte[] b = new byte[(int) file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(b);
System.out.println(b.length);
int skp = (int) (file.length()/100);
int len =skp;
//先发送一个头,表示这个一张数据的开始
byte[] b0 = "开始".getBytes();
//把开始标记发出去
DatagramPacket dp2 = new DatagramPacket(b0,b0.length, sentaddress);
socket.send(dp2);
//把文件大小用字节数组发出去
byte[] filelength=(file.length()+"").getBytes();
//将数组复制到指定长度为20的数组,不够的补0
byte[] bl=Arrays.copyOf(filelength, 20);
System.out.println("数组大小为"+file.length());
DatagramPacket dp3 = new DatagramPacket(bl,bl.length, sentaddress);
socket.send(dp3);
for(int i =0;i<100;i++){
if(i==99){
//最后剩下的长度
len=b.length-99*skp;
System.out.println(i);
System.out.println(len);
}
System.out.println(i);
System.out.println(len);
dp2 = new DatagramPacket(b, i*skp,len, sentaddress);
socket.send(dp2);
Thread.sleep(10);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
三、客户端接受到数据之后,先将其写入文件,然后再用对象流读取,读取成功才将起画在面板(这里没有判断是否成功读取对象)
while (true) {
File file0 = new File("e:/jietu.png");
//如果有原来的截图就将其删掉
if(file0.exists()){
file0.delete();
}
try {
File file = new File("e:/jietu.png");
FileOutputStream fos = new FileOutputStream(file);
byte[] b0 = new byte[4];
DatagramPacket dp0 = new DatagramPacket(b0, b0.length);
socket.receive(dp0);
// 如果是头就开始接受图片
if ("开始".equals((new String(b0)).trim())) {
int sum = 0;
byte[] blength = new byte[20];
DatagramPacket dplength = new DatagramPacket(blength,
blength.length);
socket.receive(dplength);
int length = Integer.parseInt((new String(blength)).trim());
System.out.println("大小为%%%%"+length);
int length1=length/100;
int length2=length-length1*99;
for (int i = 0; i < 100; i++) {
if (i == 99) {
byte[] buf = new byte[length2];
DatagramPacket dp2 = new DatagramPacket(buf,
buf.length);
sum++;
socket.receive(dp2);
fos.write(buf);
fos.flush();
} else {
byte[] buf = new byte[length1];
DatagramPacket dp2 = new DatagramPacket(buf,
buf.length);
sum++;
socket.receive(dp2);
System.out.println(i);
fos.write(buf);
fos.flush();
}
}
System.out.println("%%%%%" + file.length());
fos.close();
//如果sum不等于100,说明没有完成接受到图片对象,有丢失,则不能将对象完整读取出来,所以直接放弃,只有完整读取才能将其画出来
if(sum==100){
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bos = new BufferedInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(bos);
ImageIcon img= (ImageIcon) ois.readObject();
ois.close();
bos.close();
fis.close();
Graphics g = panel.getGraphics();
g.drawImage(img.getImage(), 0, 0, null);
System.out.println(">>>>>>>>>>>>>");
file.exists();
file.delete();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}