惯例先上图

晚上躺床上了,发现忘关电脑了,又不想起来关,来用手机控制电脑多好,百度了下,果然一大把。哈,我自己为什么不自己也实现个呢,任意的自己diy。Just do it。

如果不想看如何实现,那么直接用下面的吧:

web操控端:http://smallyard.cn/jobhub/

控制端jar包: http://files.cnblogs.com/files/smallyard/jobhub-client.rar

运行:java -jar joghub-client.jar [你的密码]

一、 网络通信

网络通信模块,如果自己做的话,也不是很难,就是做好了,需要买服务器来部署,这还是算了吧,为了自己玩一玩而花钱,这种事还是不干,那就用第三方的好了。

上网时,偶然发现的一个云吧,提供消息发送和消息订阅的服务。我们只需要用它把我们的控制端web和客户端监听连接起来就行了。

它有java和JavaScript的API

这时想起百度的产品里有个API store,搜索了下,果然找到了合适的接口。

二、 客户端

客户端的主要任务是接受命令并执行命令,执行命令我通过调用命令行来执行。

命令监听和发送类,主要是调用云吧的API。

/**
 * 任务监听者
 */
public class JobHandler {

    private static final String APP_KEY = "567392ee4407a3cd028aacf6";

    private static MqttAsyncClient mqttAsyncClient;

    private static String listenTopic;

    static {
        try {
            mqttAsyncClient = MqttAsyncClient.createMqttClient(APP_KEY);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 监听开始
     */
    public static void start(final String topic) {
        listenTopic = topic;
        connect();
        listen();
    }

    public static void publish(String msg) {
        try {
            mqttAsyncClient.publish(listenTopic + APP_KEY, msg.getBytes(), 1, false, null, new IMqttActionListener() {

                public void onFailure(IMqttToken arg0, Throwable arg1) {
                    System.out.println("消息返回失败");
                }

                public void onSuccess(IMqttToken arg0) {
                    System.out.println("消息返回成功");
                }
            });
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    // 连接服务器
    private static void connect() {
        try {
            mqttAsyncClient.connect(new IMqttActionListener() {
                public void onSuccess(IMqttToken arg0) {
                    System.out.println("连接服务器成功.");
                    subscribe();
                }

                public void onFailure(IMqttToken arg0, Throwable arg1) {
                    System.out.println("连接服务器失败");
                }
            });
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    private static void subscribe() {
        try {
            mqttAsyncClient.subscribe(listenTopic, 1, null, new IMqttActionListener() {
                public void onSuccess(IMqttToken asyncActionToken) {
                    System.out.println("成功监听主题: " + StringUtils.join(asyncActionToken.getTopics(), ","));
                }

                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    System.err.println("监听失败");
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 监听消息
    private static void listen() {
        mqttAsyncClient.setCallback(new MqttCallback() {
            public void connectionLost(Throwable throwable) {

            }

            public void messageArrived(String topic, MqttMessage message) throws Exception {
                String cmd = new String(message.getPayload());
                System.out.println("接收到命令:" + cmd);
                Thread thread = new Thread(new JobExecutor(cmd));
                thread.start();
            }

            public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

            }
        });
    }
}

命令执行类,调用命令行执行命令,再调用云吧API来发送执行结果。

/**
 * 任务执行
 */
public class JobExecutor implements Runnable {

    private String cmd;

    public JobExecutor(String cmd) {
        this.cmd = cmd;
    }

    public void run() {
        BufferedReader br = null;
        try {
            Process p = Runtime.getRuntime().exec(this.cmd);
            br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line).append("\n");
            }
            System.out.println(sb.toString());
            JobHandler.publish(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
            JobHandler.publish("执行失败");
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

三、 WEB端

web端的主要任务是发送命令,并接受命令执行的结果。

var hasConnect = false;
var appkey = "567392ee4407a3cd028aacf6";
var yunba = new Yunba({server: 'sock.yunba.io', port: 3000, appkey: appkey});

// 连接服务器并发送消息
function connect(cmd, topic) {
    yunba.init(function (success) {
        if (success) {
            // 连接服务器
            yunba.connect_by_customid('jobhub-web', function (success, msg, sessionid) {
                if (success) {
                    hasConnect = true;
                    console.log('你已成功连接到消息服务器,会话ID:' + sessionid);
                    // 监听回传消息
                    yunba.subscribe({'topic': topic + appkey},
                    function (success, msg) {
                        if (success) {
                            console.log('你已成功订阅频道' + topic + appkey);
                            yunba.set_message_cb(showMsg);
                            send(cmd, topic);
                        } else {
                            console.log(msg);
                        }
                    });
                } else {
                    console.log(msg);
                }
            });
        }
    });
}

// 发送消息
function send(cmd, topic) {
    yunba.publish({'topic': topic, 'msg': cmd},
    function (success, msg) {
        if (success) {
            console.log('消息发布成功');
        } else {
            console.log(msg);
        }
    });
}

// 显示回传消息
function showMsg(data){
    var msg = data.msg;
    console.log('Topic:' + data.topic + ',Msg:' + msg);

    // 替换回车
    msg = msg.replace(/\r\n|\n/g,"<br/>");
    // 替换执行失败
    msg = msg.replace("执行失败", "<span style='color:red;'>执行失败</span>");

    // 显示
    var $divMsg = $("#div_msg");
    $divMsg.append("<p>" + msg + "</p>");

    // 滚动到最下方
    $divMsg.scrollTop($divMsg[0].scrollHeight );
}

$("#btnSubmit").click(function () {
    var $inputCmd = $("#inputCmd");
    var $inputTopic = $("#inputTopic");
    var $spanInfo = $("#spanInfo");
    var cmd = $inputCmd.val();
    var topic = $inputTopic.val();
    if (!cmd) {
        $spanInfo.text("命令不能为空");
        return;
    }
    if (!topic) {
        $spanInfo.text("密码不能为空");
        return;
    }

    if (hasConnect) {
        send(cmd, topic);
    } else {
        connect(cmd, topic)
    }

    $inputCmd.val("").focus();
    // $inputTopic.val("");
    $spanInfo.text("已发送命令:" + cmd);
});

// 绑定回车事件
$(document).keydown(function(e){
    if(e.keyCode==13){
        $("#btnSubmit").click();
    }
});

  

四、 总结

想着很复杂,其实实现起来很简单的。

源码发布在github:

https://github.com/smallyard/smallyard

https://github.com/smallyard/jobhub-client

大家可以自己拿走扩充成自己喜欢的远程控制。

 

教你写一个web远程控制小工具的更多相关文章

  1. 利用 Python 写一个颜值测试小工具

    我们知道现在有一些利用照片来测试颜值的网站或软件,其实使用 Python 就可以实现这一功能,本文我们使用 Python 来写一个颜值测试小工具. 很多人学习python,不知道从何学起.很多人学习p ...

  2. 【移动端debug-6】如何做一个App里的web调试小工具

    原文链接:如何做一个App里的web调试小工具 我们知道现在hybrid app非常流行,在这样的app里,h5页面是应用非常广泛的.相对于以往在pc端开发的网页,放在app里的网页由于无法直接使用桌 ...

  3. 只有20行Javascript代码!手把手教你写一个页面模板引擎

    http://www.toobug.net/article/how_to_design_front_end_template_engine.html http://barretlee.com/webs ...

  4. 使用Node.js原生API写一个web服务器

    Node.js是JavaScript基础上发展起来的语言,所以前端开发者应该天生就会一点.一般我们会用它来做CLI工具或者Web服务器,做Web服务器也有很多成熟的框架,比如Express和Koa.但 ...

  5. 使用node.js 文档里的方法写一个web服务器

    刚刚看了node.js文档里的一个小例子,就是用 node.js 写一个web服务器的小例子 上代码 (*^▽^*) //helloworld.js// 使用node.js写一个服务器 const h ...

  6. #使用abp框架与vue一步一步写我是月老的小工具(2) 后台搭建初体验

    #使用abp框架与vue一步一步写我是月老的小工具(2) 后台搭建初体验 一.续上前言 关于这个小玩意的产品思考,假设我暂时把他叫我是月老热心人 这是一个没有中心的关系链,每个人进入以后都是以自己为中 ...

  7. 用C写一个web服务器(二) I/O多路复用之epoll

    .container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...

  8. java 写一个JSON解析的工具类

    上面是一个标准的json的响应内容截图,第一个红圈”per_page”是一个json对象,我们可以根据”per_page”来找到对应值是3,而第二个红圈“data”是一个JSON数组,而不是对象,不能 ...

  9. 半个小时教你写一个装(bi)逼(she)之地图搜租房

    半个小时教你写一个装(bi)逼(she)之地图搜租房 首先需要一个Python3环境,怎么准备我就不多说了,实在不会的出门右转看一下廖雪峰老师的博客. HTML部分 代码来自:高德API+Python ...

随机推荐

  1. [整]SQL执行顺序

    SQL的执行顺序: 第一步:FROM <left_table> <join_type> JOIN <right_table> ON <on_predicate ...

  2. CentOS系统启动流程你懂否

    一.Linux内核的组成 相关概念: Linux系统的组成部分:内核+根文件系统 内核:进程管理.内存管理.网络协议栈.文件系统.驱动程序. IPC(Inter-Process Communicati ...

  3. 腾讯TOS

    腾讯TOS 手机操作系统 3月3日开启内测[日期:2015-02-11]     来源:Linux社区  作者:Linux     [字体:大 中 小] 腾讯TOS 操作系统 3月3日开启内测 2月1 ...

  4. 使用TCMalloc的堆栈检查

    在前一篇译文<TCMalloc:线程缓冲的Malloc>详细讲解了TCMalloc的工作原理和特点,今天翻译<heap-checking using tcmalloc>,了解T ...

  5. CTO和技术副总裁应该如何分工?谁才是技术领导者?

    谁是初创公司的技术领导者,是CTO还是技术副总裁?任何在创业公司工作的人都知道,我们不应该去问这个问题.因为这两个是非常不同的角色,角色本身会随着创业公司的发展而变化,两者对于业务规模都很重要. 简单 ...

  6. .NET对象的内存布局

    每个虚拟机都有它自己的对象布局,本文我们将针对sscli源码和windbg调试器来查看不同类型的.net对象布局. 在.net虚拟机里,每个对象都需要保存这些信息: 对象的类型: 对象实例的成员属性( ...

  7. Java报表FineReport在医院院长查询分析系统中有什么用

    1.医院院长查询系统的价值 目前,大中型医院的信息处理正从传统手工方式飞速向电脑信息化建设方案转变,一个大中型医院担负着繁重的医疗和科研任务,以及繁杂的事务性工作,院长必须时刻与各科室保持密切的连续, ...

  8. KVM 介绍(8):使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机 [Nova Libvirt QEMU/KVM Live Migration]

    学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...

  9. 准备使用 Office 365 中国版--域名

    无论是购买还是试用Office 365,每个Office 365用户都会有一个唯一的ID.在中国版的Office 365中,这个ID是一个以“.partner.onmschina.cn”结尾的域名.既 ...

  10. [转]Membership 到 .NET4.5 之 ASP.NET Identity

    本文转自:http://www.cnblogs.com/jesse2013/p/membership-part3.html 我们前面已经讨论过了如何在一个网站中集成最基本的Membership功能,然 ...