最近想重温下Socket网络编程,太久没写了都快整忘记咯。
于是决定写个远程控制的软件吧。
我看了一下网上的版本,大概的思路是:分为客户端(被控制端)和服务器端(控制端)
被控制端(以下简称C端),主要做的是把自己屏幕截图,通过socket发送出去。
同时接收从服务器端发来的鼠标键盘操作,通过Robot类来实现键鼠模拟操作。
服务器端(以下简称S端),主要是接收客户端发过来的截图并通过Swing界面显示出来
同时,在界面上进行键盘鼠标操作时,将键盘鼠标命令通过Socket发送给C端。
借鉴一下大佬的代码 java实现远程控制应用,代码只需要稍微修改一下便可以运行,但是发现,S端的鼠标操作,能在C端正常模拟运行,但是S端的键盘操作,是不能通过Socket发送的,报java.io.NotSerializableException: java.io.ObjectOutputStream异常,很奇怪的是,鼠标事件和键盘事件,都是使用ObjectOutputStream来发送InputEvent对象,咋就发不出呢?然后网上一搜,果然也有人遇到这个问题:Socket无法发送按键事件,源代码中,KeyEvent是继承了EventObject,实现了序列化的,但是为什么还是报未序列化错误。这个我确实不懂,问了几个大佬,也说不出为啥,希望有大佬看到这个问题能稍微教教小弟。既然KeyEvent实现不了,那就自己定义一个实体类,序列化之后S端发送就行了,在C端进行解析。附上相关代码:
实体类
public class serEvent implements Serializable{
static final long serialVersionUID = 1L;
int keyCode;
int id;
get和set方法,带参以及不带参的构造函数
}
S端,键盘按下时操作,新建一个serEvent,通过ObjectOutputStream发送
@Override
public void keyPressed(KeyEvent arg0) {
serEvent e1=new serEvent(arg0.getID(),arg0.getKeyCode());
try {
ous.writeObject(e1);
ous.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
C端,收到事件之后,判断是鼠标还是键盘事件
Object eventobj = objins.readObject();
try {
InputEvent e = (InputEvent) eventobj;
actionEvent(e);
}catch (Exception e) {
//说明是按键事件!
serEvent e1 =(serEvent) eventobj;
actionKeyEvent(e1);
}
利用Robot去实现模拟操作
if(e.getId()==KeyEvent.KEY_PRESSED){
robot.keyPress(e.getKeyCode());
}
if(e.getId()==KeyEvent.KEY_RELEASED){
robot.keyRelease(e.getKeyCode());
}
最后成功解决键盘事件无法发送的问题。
至此,局域网内的控制端和服务器端代码已成功运行。
但是,如果想像TeamViewer或者QQ那样实现远程控制,就必须使用云服务来进行中转。
所以又在原来基础上做了个服务器中转版本。所以现在就有3个端,一个S控制端,一个C被控端,一个W网络服务器端。
代码开新帖贴上去吧。云服务器中转的远程控制JAVA代码