远程开关机程序

      背景:有一个营业厅很大,有两层,大致拥有十多台客户体验机,每台体验机其实都是一台电脑,其中主机集中放在后台的机房里,显示器和鼠键在前台,操作系统安装有美萍软件。这样就产生了一个日常问题:每天都需要到机房里把每台电脑逐个开机,下班后有需要每台电脑逐个解锁美萍然后关机(当然不排除拉电闸这种高效方法)。在这种情景下就萌生了要一个远程开关机的程序这么个需求。

首先说关机这事吧。这个实现起来途径很多,难度不大。例如windows系统便自己拥有允许远程关机这么的一个命令:

shutdown [/m \\computer]

shutdown命令允许向远程计算机发送关机指令,当然需要远程计算机端授权允许才行,如何授权?可以在组策略里找到相关选项;其次,就是使用软件关机命令,使用软件实现调用系统的api从而实现关机,这个为代码实现方法;还有就是可以使用批处理的at命令,执行计划任务,当到达下班时间便自动关机。

最后我选择了第二种,软件实现方法。排除第一种方法,是对于系统完整性和对部署机的不了解决定的,在程序正式做好投入使用之前我是没到现场见过那些体验机的,即我对目标机器完全不了解,系统是否为精简版、登录需要密码不?其次在技术研究的时候,使用了2台笔记本做实验,发现有一台无法实现关机,问题一定是处在系统配置及自身上,但是作为非专业windows维护人员,又无法通过更改配置解决问题。要是营业厅也出现这样的机器无法解决就不好了;第3中方法就太简单了,配置好计划任务后下班时间自动关机,但是领导不采纳,估计就是觉得它缺乏控制力。

开机,这个问题已开始觉得比较麻烦,后来发现这个非常容易,因为网卡正好具备了一个叫做“Wake On LAN”的功能,简单的说一下,“wake on lan” 原理。首先需要bios支持,打开bios设置,大概在电源管理里把wake on lan 设置为 enable 使能。然后向欲开机的的主机的子网发送一个广播包,包的内容为:6个“FF"+16个目标主机网卡地址。例如目标主机的mac地址是“00010203040506”,那么这个包的内容就是

FFFFFFFFFFFF0001020304050600010203040506000102030405060001020304050600010203040506

0001020304050600010203040506000102030405060001020304050600010203040506

0001020304050600010203040506000102030405060001020304050600010203040506

00010203040506

注意中间没有回车。

将以上数据以udp方法发送到7或者9端口上。这样便实现了远程开机功能。

       开机和关机的技术点就这么个解决方法。接着再说说界面问题,界面是个大问题,不知道是不是由于要把这个软件作为营业厅提高工作效率的创新工程,要求界面一定要好看,无奈经过几番修改仍达不到领导理想中的界面,请领导描述具体外观要求,又只说“要漂亮”。幸得时间有限,改到最后限期不满也得接受了。

GUI集设计和控制为一体,通过工具栏里新增布局面板和往布局面板里新增电脑,鼠标自由拖动面板和电脑的位置。右键设置参数,可自定义面板颜色和文字,通过高亮度电脑表示该主机ping得通。

界面截图


“wake on lan”是一个为现在大多数有线网卡所支持的一个功能,目前来说笔记本的无线网卡还不具备,主要是考虑到开启这个功能在关机的情况下仍会消耗一点电力,但随着低功耗硬件和高容量的电池的不断发展,让笔记本实现这个功能也是很容易的。

开启“wake on lan”功能需要在主板的bios里的电源选项里设置,记住开启该功能后即使在关机的情况下网卡仍会消耗一点电力。关机后的网卡会继续接受来着网络的数据包,当接收到开机指令时,便会启动计算机。那这条开机指令的格式是什么呢?

6*0xFF+16*MAC地址

重复六次0xFF和是六次要开机的网卡的mac地址。

一个0xFF是8位,一个mac地址是48位,6*8+16*48=816位 =102字节。

欲激活一台主机,那么就需要向该网卡发送102字节的数据包。如果使用c#的话就需要定义如下:

byte[] sendBytes = new byte[102];

无论激活哪台及其,数据包的前6字节都是一样的,都是0xFF。如果使用c#的话:

for (int i = 0; i < 6; i++)
           {
               sendBytes[i] = 0xFF;
           }

接下来就是填充mac地址了。我们在这里做个假设,目标机器的网卡mac为:

08-00-27-00-D8-9A

对输入的mac要处理一下

string macAddress=”08-00-27-00-D8-9A”;

macAddress = macAddress.Replace(":", "").Replace("-", "");

当然,需要将这个字符串处理一下,使之转化为byte类型,如果使用c#的话,可以使用 byte.Parse()方法将字符串转换为byte类型。例如:

byte test=byte.Parse(“FF”,System.Globalization.NumberStyles.HexNumber);

可以将字符串“FF"转为0b11111111。那么将上面的mac地址字符串转为byte字节数组,就是每次取两个字符串变为一个字节。

for (int i = 0; i < 16; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    sendBytes[(i + 1) * 6 + j] = byte.Parse(macAddress.Substring(j * 2, 2),    System.Globalization.NumberStyles.HexNumber);
                }
            }

由于要重复16次,所以在上一层多嵌套一个for循环。经过上述,一个102字节的开机数据包就准备好了。接下来就是要发送出去。

怎么发,使用UDP协议发送便可,发送到端口7或者端口9。发送到哪个地址,只要目标机器能收到便可,在局域网内一般以发送广播包的形式发送(255.255.255.255 为广播地址)。

UdpClient udpClient = new UdpClient();

udpClient.Send(sendBytes, sendBytes.Length, “255.255.255.255”, 7);

这样便完成了一个简单的远程开机功能。

对于发送的目标地址,我再说上两句。在局域网内发送广播包可以让网内的所有机器都收到给数据包。那么广域网能不能也实现开机这个功能呢?也是行的,只要保证能让目标主机的电脑接收到这个数据包就行了。假设你现在在外面,家里有台电脑,使用adsl宽带,电脑是连接路由的,路由再连接adsl拨号上网的。只要你路由没关,adsl没关,那么你就有一个ip地址,你在外网往这个ip地址发送数据,就会被路由收到(当然还到达不了你的机器),此时,你需要设置路由映射,让来自外网发送到路由端口7的数据转发到你的机器上,那么你的机器就能收到这个数据包了。

更多关于wake on lan的介绍还是得去看看专业文档。


转载请注明:来自李鑫 
本文地址:http://www.lixin.me/2011/10/30/17007.lixin

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值