使用Websocket实现html页面远程控制-(中转服务-傀儡端)(原理)

  • Post author:
  • Post category:其他




使用Websocket实现html页面远程控制-(中转服务-傀儡端)(原理)

简介:远程控制,当网络互通时可直接将傀儡端(即被控制的一方)的信息发送到前端html页面,页面将命令直接发送傀儡端控制.但是在当网络不通时无法直接控制,需要中转服务来转发消息,傀儡端和控制端可以不在同一个网段,只需要都能和中转服务通信就能实现远程操控.本次只描述中转服务,和傀儡端的原理,都由Java语言实现.



远程操控平台介绍

该操作平台分为三个部分,控制端,中转服务(简称为服务器),傀儡端.



控制端:
  • 控制其他PC,打开浏览器即可不需下载任何插件或应用即可进行远程操控,需要接受服务器发送的画面信息,并发送指令到中转服务.


傀儡端:
  • 被控制的一方,由java实现,需要实时发送该pc的显示画面到服务器,并执行服务器转发到傀儡端的指令.


服务器
  • 连接傀儡端和控制端,傀儡端和控制端可以不在一个网段,但只要都能和服务器连接就能进行远程操控,主要功能是接收傀儡端的画面信息转发到控制端,接收控制端的指令转发到傀儡端.



远程操控服务端实现原理简介

因为要与控制端html进行实时交互,所以采用websocket协议连接,发送JSON对象为信息载体,为了方便,傀儡端和服务端相连也采用websocket.

//传输对象
public class MessageDTO {
    private String from; //发出本次信息的id
    private String to;	//需要接收这个信息的id
    private TypeEnum type;//p-s  c-s 类型傀儡端到服务器还是控制端到服务器
    private String image; //图片信息
    private AllEvent allEvent; //需要傀儡端执行的事件 包括鼠标事件和键盘事件等
}

服务端提供三个map分别存放客户端连接session(下文中简称clientMap),傀儡端连接session(下文简称puppetMap).以及客户端与傀儡端对应关系(clients_puppers).

  • 当客户端连接根据url携带的参数将session放到clientMap中保存,将傀儡端和控制端关系放到clients_puppers中.
  • 当傀儡端连接,根据url携带参数将session放到puppetMap.
    /***
     * @Author: yeguangrui
     * @Date: 2020/12/3 11:31
     * @param session 当前连接的会话
     * @param from  从哪里来的
     * @param to  如果是客户端 需要发送监控哪个id的动向 傀儡段不需要可以为任意值
     * @param from    自己的唯一id
     * @return: void
     * 功能描述:
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("type") String type, @PathParam("to") String to, @PathParam("from") String from) {
        if (type.equals(TypeEnum.PUPPET_SERVER.toString())) {
            puppets.put(from, session);
        } else if (type.equals(TypeEnum.CLIENT_SERVER.toString())) {
            clients.put(from, session);
            clients_puppers.put(from, to);
        } else {
            log.error("type error");
        }
    }
  • 当客户端发送来消息,根据参数携带的参数傀儡端id,从PuppetMap中取出该傀儡端与服务器连接的session将该信息发送给傀儡端,完成控制指令传输.
  • 当傀儡端发送来消息,根据自身傀儡端id从relationMap中取出控制该傀儡端的客户端id,再用此id从clientMap中取出客户端与服务端连接的session,将画面信息用此session发送到傀儡端.
 /**
     * @Author: yeguangrui
     * @Date: 2020/12/16 14:53
     * @param message 接收到的信息
     * @return: void
     * 功能描述:接受信息,
     * 如果是客户端来的 将信息发送给傀儡端执行,
     * 如果是傀儡端来的遍历 对照关系map找到所有控制傀儡段的 客户端,发送图片信息
     */
    @OnMessage
    public void onMessage(String message) {
        MessageDTO messageDTO = JSONObject.parseObject(message, MessageDTO.class);
        //如果是客服端到服务器 ,发送给傀儡端
        if (messageDTO.getType().equals(TypeEnum.CLIENT_SERVER)) {
            String toId = messageDTO.getTo();
            //log.info(toId);
            this.sendMessageDTO(puppets.get(toId), messageDTO);
        }
        //如果是傀儡段到服务器 查出来控制该傀儡的所有客户端id并且发送该信息
        else {
            //  puppertMessage.put(messageDTO.getFrom(), messageDTO);
            for (String clientId : clients_puppers.keySet()) {
                //获取傀儡段id和消息来源id相同
                if (clients_puppers.get(clientId).equals(messageDTO.getFrom())) {
                    this.sendMessageDTO(clients.get(clientId), messageDTO);
                }
            }
        }
    }
  • 当客户端断开连接,从clients_puppers和clientMap中删除该session的信息.
  • 当傀儡端断开连接,从puppetMap和clients_puppers中删除该session信息.



远程操控傀儡端实现原理简介

傀儡端功能

  • (通过websocket)实时发送自己的桌面信息到服务器再由服务器转发到前端页面,桌面信息为当前桌面截图(通过Java Robot类实现)
  • 当接收到服务器的信息,解析传输对象,(通过Robot)执行事件对象中包含的信息(鼠标事件为哪个键,按压,释放),键盘事件为(哪个键,按压还是释放) 键盘事件对象:
public class MasterKeyEvent {
    /**
     * 按键状态
     * TRUE.按下
     * FALSE.释放
     */
    private boolean pressed;
    private Integer keyCode;
}



遇到的问题以及解决办法

  • websocket传输图片过大超过了限制,需要自己实现ServletContextInitializer:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class WebAppRootContext implements ServletContextInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.addListener(WebAppRootListener.class);
        servletContext.setInitParameter("org.apache.tomcat.websocket.textBufferSize", "1024000");
    }
}
  • 图片过大传输慢,控制端展示慢,延迟高:使用谷歌的图片压缩thumbnailator压缩图片:
	<dependency>
    	<groupId>net.coobird</groupId>
    	<artifactId>thumbnailator</artifactId>
    	<version>0.4.9</version>
	</dependency>
  • 鼠标问题:JavaRobot类截图会隐藏鼠标,需要自己绘制鼠标,但是绘制鼠标,前端页面不显示鼠标,延迟感会较为明显,采用控制端自己的鼠标会移动鼠标不会卡.
  • 鼠标事件问题:当控制端发送ctrl,alt等键按下事件时前端会弹出相应win界面,导致前端监控不到相应的键释放事件,傀儡端当按下这些键时定时5s后自动执行释放事件.
  • 傀儡端发送图片过于频繁问题,增加图片比较类,比较前一个图片与当前图片是否相同,相同则不发送,可以减少传输.
  • 图片格式问题,采用其他图片格式较大,加载慢,后采用jpeg格式图片.



版权声明:本文为qq_42867665原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。