基于NodeJS的远程控制程序.
发布于 2年前 作者 chrome10086 13731 次浏览

先上图: enter image description here enter image description here

介绍: 采用css+javascript+nodejs编写.css+javascript主要用于编写操作界面.目前只支持chrome,其他浏览器没测试.核心部分采用nodejs的http模块和websocket编写. http模块用于客户端上线.websocket用于核心程序和操作界面实时交互数据.
目前基于测试目的.客户端代码用js写了简单的上线和执行cmd命令的功能.(方便测试,所以操作都为同步)

工作流程: 运行主程序(websocket工作,监听一个端口)------->打开界面程序------>设置上线端口(连接主程序,通过websocket交互数据)------>主程序收到上线端口的数据后----->建立http服务,设置上线端口,等待客户上线-------->如果客户上线.便通知控制界面!

后期工作: 客户端代码改为c/c++编写.主程序使用net模块编写. 完善(添加)功能.

贴上主程序的演示代码 初学练手代码.献丑了.

var WebSocketServer = require('./ws').Server;     // websocket 服务
var wss = new WebSocketServer({port : 12347});    // websocket 端口 默认 12347
var all_id={};                                    // 所有上线记录器
var cmd={};
var temp_port;                                    // 上线端口 http 使用
console.log("\u670D\u52A1\u5668\u542F\u52A8\u6210\u529F.");   //服务器启动成功

wss.on('connection', function (ws) {              // websocket 连接事件 
    
temp_port=ws.upgradeReq.url.replace("/","");  // websocket 接收的http端口  如 : ws://localhost:12347/80   80即为 发送的端口 
http = require("http").createServer(function (request, response) { 
var buffers='';
request.setEncoding("ascii"); 
request.addListener("data",function(data){ 
    data=unescape(data);
    switch (request.url){    // 判断提交的地址 如 /onolne 为上线  /con 为连接/心跳   
           case "/online":  {      //// 上线 操作  ////
                              var s=eval("("+data+")");              // 把接收到的数据 转成json
                              s.Wan_ip=request.connection.remoteAddress;
                              //console.log();
                              all_id[s.ID]=s;                    // 记录一个上线id 
                              cmd[s.ID]=s;                  
                              cmd[s.ID].cmd="";                  //设置cmd初始
                              all_id[s.ID].keep=0;               // 用于判断 在线状态的 变量  第一次上线设置为0 心跳后 设置为1   
                              ws.send(json2str(s));                     // 把数据发送为管理页面 
                              console.log(s.ID);      // 显示id
                              setInterval(function(id){          // 设置定时器  检查在线情况 
                              if(all_id[id].keep != 1)           // 判断是否为1 不是1 说明 服务端心跳没来请求 (请求后会设置为1)
                               {                                    
                                ws.send("{'ID':"+id+",'status':'1'}");  // 不是1 服务端已经离线 发送离线数据 给管理页面
                                delete all_id[id];                      // 清除离线的服务端
                                console.log(id+" is offine");           // 显示清除信息
                                clearInterval(this);                    // 清除该定时器
                               } else {                             
                                all_id[id].keep = 0;             // 如果是 1 说明刚才有心跳请求 重置为 0 
                               }
                              },17000,s.ID);                   
                              response.writeHead(200,{"Content-Type":"text/plain"});   //返回http数据
                              response.write(escape(s.Time));                                    //返回http数据
                              response.end();                                          //返回http数据
           
                          }                                       ///////////////////////////////////////// 上线 操作  ////////////////////////////////////////////
                               break;                              
           case "/con":     { 
                              var c=eval("("+data+")");                 ///////////////////////////////////////// 心跳 操作  ////////////////////////////////////////////
                              all_id[c.ID].keep=1;   // 用于判断 在线状态的 变量  第一次上线设置为0 一次心跳后 设置为1
                              ws.send(data);
                              if(cmd[c.ID].cmd != "" ) {
                              response.writeHead(200,{"Content-Type":"text/plain"});    //返回http数据
                              response.write(escape(cmd[c.ID].cmd));                          //返回http数据 (给客户端的命令)
                              response.end(); 
                              cmd[c.ID].cmd="";
                              } else {
                              response.writeHead(200,{"Content-Type":"text/plain"});     
                              response.write(escape(c.ID));                                      //返回http数据
                              response.end();                                            
                              }
                            
                          }           
                           break;
                          ///////////////////////////////////////// 心跳 操作  ////////////////////////////////////////////
                          
         case "/outcmd":     {             

                              buffers+=data;     
                            
                          }               
                               break;
           default:        {
                              response.writeHead(404,{"Content-Type":"text/plain"});  
                              response.end();                                          //返回http数据
                          }
                               break;
                       }
      
});

request.addListener("end", function() {

switch (request.url){                                                    // 判断提交的地址 如 /onolne 上线  /con  连接/心跳   
           case "/outcmd":  {
                              //console.log(buffers);
                              var b=eval("("+buffers+")");
                              ws.send(buffers);
                              response.writeHead(200,{"Content-Type":"text/plain"});  
                              response.write("OK_"+b.ID);                                      //返回http数据
                              response.end(); 
           } break;
           default:   break;
}});

}).listen(temp_port,function(){   
console.log("open port "+temp_port);    
});              

  ws.on('message', function (message) { // websocket 接收控制页面数据
         var d=eval("("+message+")");
         cmd[d.id].cmd=d.cmd;
      });
  ws.on('close', function (e) { 
          console.log("close port "+temp_port); 
          process.exit();
     }); });
function json2str(o) {   // json 转 字符串
var arr = [];
var fmt = function(s) {
if (typeof s == 'object' && s != null) return json2str(s);
return /^(string|number)$/.test(typeof s) ? "'" + s + "'" : s;
}
for (var i in o) arr.push("'" + i + "':" + fmt(o[i]));
return '{' + arr.join(',') + '}';
}
10 回复

学习了. 如果是用socket来写 主程序服务 就好了.

求完整源码啊.

very good,学习了.

用socket.io可以解决websocket方面的问题, 心跳socket.io server - client 会做维持.

我最近做了一个远程控制win7 上tomcat的应用, 基于 ruby + sinatra, 原理估计跟你的差不多。 类似 tail -f catalina.out 这种指令能实现么?

不错 比现在好多卖的bs架构的远控都好…

我刚做的一个东西应该和你的需求差不多。

用 ChildProcess.spawn 执行 tail -f catalina.out ,然后通过 stdout 持续获得 shell 命令的输出,读到换行就把给这一行转成文本格式发给前端。

回到顶部