数码产品种类越来越多,让人目不暇接。当多种数码产品以及电脑、网络等放到一起的时候,就是我们充分发挥想象力,创造各种奇特的应用的时候了。
就拿这开机说起吧。当只有一台电脑的时候,开机是件再普通不过的事情了,轻轻按一下电源,开机就实现了。而当有两台电脑时,一台电脑已经打开了,现在我要打开另一台,是不是一定要站起来,走过去,按下电源呢?答案就不一定了。这里我要举两个例子,一是用一台电脑为另一台电脑开机,二是用手机让电脑开机。
如果要实现电脑的远程开机,一是要电脑的电源支持,二是要主板支持,三是要网卡支持,四是要控制远程开机的电脑与被控制的电脑在同一局域网内。幸运的是,现在大多数电源与集成网卡的主板是满足前三个条件的,只不过可能需要再BIOS里做些设置,例如要允许网卡BIOS、允许Wake up on LAN等。而第四个条件,对于数字家庭来说就更满足了。一个典型的scenario是:一个家庭有一台台式机和一台笔记本电脑,台式机通过网线连到无线路由器上,而笔记本则通过无线网上网。这家主人抱着笔记本来到厕所大号,突然想访问台式机上的一个文件,这时就可以通过运行一个远程开机软件来远程打开台式机,然后访问里面的资源。这种远程开机软件原理非常简单,完全可以自己写的,例如下面就是一段完整的实现远程开机的代码:(VC6编译)
- WSADATA data;
- WSAStartup(MAKEWORD(2, 0), &data); //初始化socket环境
- SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); //创建一个UDP SOCKET
- bool val = 1;
- setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&val, sizeof(val));//设置广播模式
- unsigned char mac[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; //假设你的台式机网卡的MAC地址是00-11-22-33-44-55
- char buf[102]; //准备数据包,远程开机其实就是发送一个102字节长的UDP广播包
- memset(buf, 0xff, 6); //前六个字节固定都是0xff
- for(int i = 0; i < 16; i++) //之后把MAC地址重复16遍
- memcpy(&buf[i * 6 + 6], mac, 6);
- sockaddr_in to;
- to.sin_family = AF_INET;
- to.sin_port = 0;//端口无所谓的
- to.sin_addr.s_addr = htonl(INADDR_BROADCAST); //发送数据到广播地址
- sendto(sock, buf, 102, 0, (sockaddr*)&to, sizeof(to)); //发送。到这步时台式机就启动了
- closesocket(sock);//关闭SOCKET
稍有点C++和Winsock编程的基础的人应该很容易看懂这段代码,注意编译之前要include <winsock.h>,并且加上对ws2_32.lib的引用。把这段代码编译成一个基于控制台的EXE文件,拷到WINDOWS目录下,之后想开机时就可以直接按WIN+R,输入你的EXE的名字,就可以开机了。
另一种情况是你的笔记本电脑没有打开,但你拥有一台支持Wi-Fi的手机,那么你一样可以通过手机来远程打开电脑。这里以可以运行.Net程序的Windows Mobile环境为例,把上面的C++代码直接翻译成C#代码:
- static void Main()
- {
- Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
- // s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, new byte[] { 1});
- byte[] data = new byte[102];
- for(int i = 0; i < 6; i++)
- data[i] = 0xff;
- for(int i = 0; i < 16; i++)
- {
- data[i * 6 + 6] = 0x00;
- data[i * 6 + 7] = 0x11;
- data[i * 6 + 8] = 0x22;
- data[i * 6 + 9] = 0x33;
- data[i * 6 + 10] = 0x44;
- data[i * 6 + 11] = 0x55;
- }
- System.Net.IPEndPoint addr = new System.Net.IPEndPoint( new System.Net.IPAddress(0xFFFFFFFF), 0);
- s.SendTo(data, addr);
- s.Close();
- }
容易发现这段代码的原理与之前的大致相同,唯一不同的就是被注释掉的一行,它本来是用来设计Socket的广播模式的,在PC上运行时这一行是必须的,否则在调用SendTo方法时被有异常,但在手机上运行时这一行是不能要的,原因是SocketOptionName.Broadcast这个选项不受.NET Compact Framework支持,而不设置这个选项在手机一样可以发出广播包。
把这段C#代码编译成EXE文件,放到Windows Mobile环境下运行一下,果然成功。由此,我们进行了数字家庭的大门,为以后坐在沙发上什么都能干做出了迈出了第一步。