**
这是客户端
**
package Remote;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/**
- 客户端(控制端)
- @author jingxiangxiang
/
public class ShccClient {
public static void main(String[] args)throws Exception {
/
*通过ip地址连接对应的服务器 接收serverSocket.accept() 通信
*(可以对应多个)
*/
// System.out.println(“请输入连接服务IP地址:”);
// Scanner scanner = new Scanner(System.in);
// String next = scanner.next();
Socket client = new Socket(“192.168.0.110”,7777);
DataInputStream dataIn=new DataInputStream(client.getInputStream());
//创建窗体
ClientUI ui =new ClientUI(new ObjectOutputStream(client.getOutputStream()));
ui.setSize((int)dataIn.readDouble(),(int) dataIn.readDouble());
byte[] buf;
while(true) {
buf=new byte[dataIn.readInt()];//和writeInt对应
dataIn.readFully(buf);
//设置图到背景窗口中去
ui.setImage(buf);
}
}
}
class ClientUI extends JFrame {
public JLabel backImage;//背景图片的对象
private ObjectOutputStream objectOut;//对象输出流(这里序列化和反序列化传出去)
public ClientUI(ObjectOutputStream objectOut ) {
//将外部的输出流传递进来
this.objectOut=objectOut;
//设置客户端窗体上面的标题
this.setTitle("上海长城电子信息网络有限公司苏州分公司");
//设置窗体尺寸
this.setSize(1024,768);
//窗体关闭的时候退出应用程序
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
backImage=new JLabel();
//创建滚动条,(解决不同分辨率)
JPanel pane=new JPanel();
//滚动条面板
JScrollPane scrollPane=new JScrollPane(pane);
//屏幕的背景对象添加到面板
pane.add(backImage);
this.add(scrollPane);
//设置屏幕居中
this.setLocationRelativeTo(null);
/**
* 这里开始通过鼠标,键盘事件(通过接口)
*/
//这里是鼠标的点击事件
backImage.addMouseListener(new MouseListener() {
//当鼠标按下的时候
public void mouseReleased(MouseEvent e) {
System.out.println("(客户端mouseReleased)进入鼠标事件");
sendEventObject(e);
}
//当鼠标松开的时候
public void mousePressed(MouseEvent e) {
System.out.println("(客户端mousePressed)进入鼠标事件");
sendEventObject(e);
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
});
//这里是鼠标移动的事件
backImage.addMouseMotionListener(new MouseMotionListener() {
public void mouseMoved(MouseEvent e) {
System.out.println("(客户端mouseMoved)进入鼠标事件");
sendEventObject(e);
}
public void mouseDragged(MouseEvent e) {
System.out.println("(客户端mouseDragged)进入鼠标事件");
sendEventObject(e);
}
});
//键盘事件(键盘不是一个输入对象,所以不用backImage)
this.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
sendEventObject(e);
}
public void keyReleased(KeyEvent e) {
System.out.println("(客户端)进入 keyReleased键盘事件");
sendEventObject(e);
}
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed客户端键盘事件");
sendEventObject(e);
}
});
//设置可见
this.setVisible(true);
}
/*
* 更新图片(用来更新图片的)
*/
public void setImage(byte[] image) {
backImage.setIcon(new ImageIcon(image));
}
//鼠标、键盘事件被确定后,通过InputEvent对象发送到服务端
public void sendEventObject(InputEvent event) {
try {
//将对象(鼠标、键盘相关操作)事件传递到服务端
System.out.println("客户端sendeventObjiet方法");
objectOut.writeObject(event);
System.out.println("客户端sendeventObjiet方法结束");
objectOut.flush();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("客户端sendeventObjiet异常");
e.printStackTrace();
}
}
}
这里是服务端
package Remote;
import java.awt.AWTException;
import java.awt.Event;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import com.sun.image.codec.jpeg.*;
/**
- 服务端(被控制端)
- @author jingxiangxiang
/
public class ShccService {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(7772);
//System.out.println(“等待客户端连接…”);
/*
* 接收单个(客户端)连接
/
System.out.println(“等待连接…”);
//accept等待,阻塞的方法
Socket client= serverSocket.accept();//接收请求
System.out.println(“连接成功”);
ImageThread imgThread =new ImageThread(new DataOutputStream(client.getOutputStream()));
//启动图片宽口化线程
imgThread.start();
//启动键盘、鼠标事件线程
EventThread eventThread= new EventThread(new ObjectInputStream(client.getInputStream()));
eventThread.start();
/*
* 等待多个(客户端)连接
*/
// while(true) {
// System.out.println(“等待客户端连接…”);
// //accept等待,阻塞的方法
// Socket client= serverSocket.accept();//接收客户端传过来请求
// System.out.println(“客户端连接成功”);
// ImageThread imgThread =new ImageThread(new DataOutputStream(client.getOutputStream()));
// //启动图片宽口化线程
// imgThread.start();
// //启动键盘、鼠标事件线程
// EventThread eventThread= new EventThread(new ObjectInputStream(client.getInputStream()));
// eventThread.start();
// }
}
}
/**
* 在服务捕获图片,
* 传送给客户端
* (使用子线程去传输)
*/
class ImageThread extends Thread{
private DataOutputStream dateOut;//创建一个输出流属性
//创建构建方法传递输出流
public ImageThread(DataOutputStream dateOut ) {
this.dateOut=dateOut;
}
//这里重写了父类的方法
public void run() {
try {
Robot robot=new Robot();
//获取系统默认的工具包
Toolkit toolkit = Toolkit.getDefaultToolkit();
//创建一个Rectangle(矩形)对象,坐标是0.0高度是屏幕尺寸
Rectangle rect=new Rectangle(toolkit.getScreenSize());
//自适应屏幕的宽和高
dateOut.writeDouble(toolkit.getScreenSize().getHeight());//设置屏幕高
dateOut.writeDouble(toolkit.getScreenSize().getWidth());//设置屏幕宽
dateOut.flush();//手动刷新
BufferedImage bufImg;
byte[] imgBytes;
while(true) {
//获取当前的屏幕
bufImg = robot.createScreenCapture(rect);
//将获取的图片转换成字节流数组,方便传输
imgBytes=getImageButes(bufImg);
dateOut.writeInt(imgBytes.length);
//输出
dateOut.write(imgBytes);
//手动刷新
dateOut.flush();
Thread.sleep(100);
//------到这里就是去客户端接收
}
} catch (Exception ex) {
// TODO: handle exception
}
}
/*
* 图片
* 装换二进制流
*
*/
public byte[] getImageButes(BufferedImage image) throws ImageFormatException, IOException{
ByteArrayOutputStream baos=new ByteArrayOutputStream();
JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(baos);
encoder.encode(image);
return baos.toByteArray();
}
}
/**
* 这里用来接收客户端操作事件进行解析
* (接收客户端鼠标 、键盘操作在这里解析,)
*/
class EventThread extends Thread{
//接收(鼠标。键盘)事件,将事件传进来
private ObjectInputStream objInput;
private Robot robot;
//这里建立一个构造方法接收
public EventThread(ObjectInputStream obj) {
this.objInput=obj;
}
//重写run方法
//启动线程重写run方法
public void run() {
try {
//模拟操作鼠标和键盘用robot
robot=new Robot();
InputEvent event;
//用while循环不停的接收客户(解析)端事件
while(true) {
Object eventobj = objInput.readObject();
event = (InputEvent) eventobj;
// event=(InputEvent)objInput.readObject();
//将操作用doevent方法进行解析
doEvent(event);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//这里开始解析客户端穿过来的(键盘,鼠标)事件
public void doEvent(InputEvent event) {
// 键盘事件/鼠标事件
//键盘事件
// if(event instanceof KeyEvent) {
// //将客户端的事件强转成键盘事件,
// KeyEvent key=(KeyEvent)event;
//
// //判断键盘事件类型(是键盘按下去还是键盘弹起)
// int type =key.getID();//获取类型
// if(type == Event.KEY_PRESS) {
// //键盘按下的时候
// robot.keyPress(key.getKeyCode());
// }else if(type == Event.KEY_RELEASE) {
// //键盘释放的时候
// robot.keyRelease(key.getKeyCode());
// }
// }
if(event instanceof KeyEvent) {
//将客户端的事件强转成键盘事件,
KeyEvent key=(KeyEvent)event;
//判断键盘事件类型(是键盘按下去还是键盘弹起)
int type =key.getID();//获取类型
if(type == key.KEY_PRESSED) {
//键盘按下的时候
robot.keyPress(key.getKeyCode());
}else if(type == KeyEvent.KEY_RELEASED) {
//键盘释放的时候s
robot.keyRelease(key.getKeyCode());
}
}
// if(event instanceof KeyEvent){
// KeyEvent ke=(KeyEvent) event;
// if(event.getID()==KeyEvent.KEY_PRESSED){
// robot.keyPress(ke.getKeyCode());
// }
// if(event.getID()==KeyEvent.KEY_RELEASED){
// robot.keyRelease(ke.getKeyCode());
// }
// }
//鼠标事件
else if (event instanceof MouseEvent) {
MouseEvent mouseEvent=(MouseEvent)event;
int type =mouseEvent.getID();
//这里和键盘事件不同,和robot事件执行方法不一样。
if(type == Event.MOUSE_DOWN) {
//鼠标点击
robot.mousePress(getButtons(mouseEvent.getButton()));
}else if (type == Event.MOUSE_UP) {
//鼠标释放
robot.mouseRelease(getButtons(mouseEvent.getButton()));
}else if(type == Event.MOUSE_MOVE) {
//鼠标移动事件
robot.mouseMove(mouseEvent.getX(), mouseEvent.getY());
}else if (type == Event.MOUSE_DRAG) {
//鼠标拖动事件(mouseEvent鼠标已经点击过了,所以和移动事件一样)
robot.mouseMove(mouseEvent.getX(), mouseEvent.getY());
}
}
}
//鼠标事件对象转换成输入对象(鼠标事件比键盘事件特殊,要通过butto转换然后在doEvent方法中进行解析)
public int getButtons(int button) {
//robot鼠标传递的是button_mask,
if(button == MouseEvent.BUTTON1) {
return InputEvent.BUTTON1_MASK;
}else if (button == MouseEvent.BUTTON2) {
return InputEvent.BUTTON2_MASK;
}else if (button == MouseEvent.BUTTON3) {
return InputEvent.BUTTON3_MASK;
}
return -1;
}
}
***
这里是报错内容
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: java.io.ObjectOutputStream
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
at java.io.ObjectInputStream.defaultReadObject(Unknown Source)
at java.awt.event.KeyEvent.readObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeReadObject(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at Remote.EventThread.run(Service.java:152)
Caused by: java.io.NotSerializableException: java.io.ObjectOutputStream
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at Remote.ClientUI.sendEventObject(ShccClient.java:170)
at Remote.ClientUI$3.keyPressed(ShccClient.java:148)
at java.awt.Component.processKeyEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Window.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue
3.
r
u
n
(
U
n
k
n
o
w
n
S
o
u
r
c
e
)
a
t
j
a
v
a
.
s
e
c
u
r
i
t
y
.
A
c
c
e
s
s
C
o
n
t
r
o
l
l
e
r
.
d
o
P
r
i
v
i
l
e
g
e
d
(
N
a
t
i
v
e
M
e
t
h
o
d
)
a
t
j
a
v
a
.
s
e
c
u
r
i
t
y
.
P
r
o
t
e
c
t
i
o
n
D
o
m
a
i
n
3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain
3.run(UnknownSource)atjava.security.AccessController.doPrivileged(NativeMethod)atjava.security.ProtectionDomainJavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue
4.
r
u
n
(
U
n
k
n
o
w
n
S
o
u
r
c
e
)
a
t
j
a
v
a
.
s
e
c
u
r
i
t
y
.
A
c
c
e
s
s
C
o
n
t
r
o
l
l
e
r
.
d
o
P
r
i
v
i
l
e
g
e
d
(
N
a
t
i
v
e
M
e
t
h
o
d
)
a
t
j
a
v
a
.
s
e
c
u
r
i
t
y
.
P
r
o
t
e
c
t
i
o
n
D
o
m
a
i
n
4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain
4.run(UnknownSource)atjava.security.AccessController.doPrivileged(NativeMethod)atjava.security.ProtectionDomainJavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)