先上图:
介绍:
采用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 回复