远程开机的原理与代码实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chinapxe/article/details/72571301
继续聊一个无客户端的话题,很多机房管理软件中的常见的一个功能:远程开机,电脑是关闭就算电脑中安装了你客户端关机状态下也没有运行,是如何响应指令呢,肯定不是通过客户端了。
其实远程开机就是一种网络唤醒(Wakeup On LAN)绝大多数电脑的主板BIOS  都支持这项功能,如果BIOS 中没有开启则需要手工打开。电脑没有开机前网卡没有IP 地址,网络通讯时该如何发送数据? 这里就要用到广播包,广播包顾名思意就是不针对具体的目标向一个网段范围内所有的地址同时发出,和你用收音机接收广播的道理相同。


网络唤醒数据包的结构,这个是规范按规范来就可以了:
UDP广播包,端口不限
数据是 
FF-FF-FF-FF-FF-FF 接着目标计算机的 MAC 地址重复 16 次
注意,这里是UDP 的广播包,与我们前面分享中均使用的TCP 有一定的区别


直接上代码:
void CAppRunServerView::StartNETPC( CString MACstr )
{
    int dstaddr[6];
    char mac[20];
    int j;
    for (  j=0;j<MACstr.GetLength();j++ )
    {
        mac[j]= MACstr.GetAt(j);
    }
    mac[j]='\0';
    int i = sscanf( mac,"%2x:%2x:%2x:%2x:%2x:%2x",
                       &dstaddr[0],
                       &dstaddr[1],
                       &dstaddr[2],
                       &dstaddr[3],
                       &dstaddr[4],
                       &dstaddr[5]);
    if (i!=6)
    {
        return;
    }
    unsigned char ether_addr[6];
    for( i=0; i<6; i++ )
        ether_addr[i]=dstaddr[i];
    //构造Magic   Packet
    unsigned char magicpacket[200];
    memset(magicpacket,0xff,6);
    int packetsize=6;
    for ( i=0; i<16; i++ )
    {
        memcpy( magicpacket + packetsize , ether_addr, 6 );
        packetsize += 6;
    }
    WSADATA WSAData;
    if( WSAStartup( MAKEWORD(2,0), &WSAData ) != 0 )
    {


        return;
    }
    //创建socket
    SOCKET sock = socket( AF_INET,SOCK_DGRAM,0 );
    if ( sock == INVALID_SOCKET )
    {


        return;
    }
    //设置为广播发送
    BOOL bOptVal=TRUE;
    int iOptLen=sizeof(BOOL);
    if ( setsockopt( sock, 
                     SOL_SOCKET, 
                     SO_BROADCAST, 
                    (char*)&bOptVal,iOptLen) == SOCKET_ERROR )
    {
        closesocket(sock);
        WSACleanup();
        return;
    }
    sockaddr_in to;
    to.sin_family = AF_INET;
    to.sin_port = htons(0);
    to.sin_addr.s_addr = htonl( INADDR_BROADCAST );
    //发送Magic   Packet
    if ( sendto( sock,(const char*)magicpacket,packetsize,0,
                ( const    struct sockaddr*)&to, 
                sizeof(to) )==SOCKET_ERROR )
    {
        return;
    }
    else
    {
        //MessageBox( _T("发送成功") );
       
    }
    closesocket(sock);
    WSACleanup();
}



有几个前提条件,这台电脑的MAC 这肯定得先知道(废话)
这台电脑的BIOS  支持网络唤醒;
这台电脑在网络(交换机)上曾经至少至少工作过一次与别人通讯过一次,只有这样交换机中的MAC 表才对客户机有记录。否则再帅从没有打过卡前台妹纸也不能让你只刷新脸啊。
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页