局域网唤醒 (PHP) 无法使其正常工作



试图让 php 唤醒局域网工作(通过互联网)。

通过 wolcmd 程序,我可以使用以下命令成功从互联网打开服务器:

/Users/usr/Downloads/wolcmd [mac] [public IP] 255.255.255.255 1009

所以没有路由器/服务器问题。

我在互联网上找到了几个php脚本,但没有一个有效! :S

试:

<?php
flush();
function WakeOnLan($addr, $mac,$socket_number) {    
  $addr_byte = explode(':', $mac);
  $hw_addr = '';
  for ($a=0; $a <6; $a++) $hw_addr .= chr(hexdec($addr_byte[$a]));
  $msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
  for ($a = 1; $a <= 16; $a++) $msg .= $hw_addr;
  // send it to the broadcast address using UDP
  // SQL_BROADCAST option isn't help!!
  $s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
  if ($s == false) {
    echo "Error creating socket!n";
    echo "Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s));
    return FALSE;
  } else {
    // setting a broadcast option to socket:
    $opt_ret = socket_set_option($s, 1, 6, TRUE);
    if ($opt_ret < 0) {
      echo "setsockopt() failed, error: " . strerror($opt_ret) . "n";
      return FALSE;
    }
    if (socket_sendto($s, $msg, strlen($msg), 0, $addr, $socket_number)) {
      echo "Magic Packet sent successfully!";
      socket_close($s);
      return TRUE;
    } else {
      echo "Magic packet failed!";
      return FALSE;
    }
  }
}
// Port number where the computer is listening. Usually, any number between 1-50000 will do. Normally people choose 7 or 9.
$socket_number = "1009";
// MAC Address of the listening computer's network device
$mac_addy = "XX:XX:XX:XX:XX:XX";
// IP address of the listening computer. Input the domain name if you are using a hostname (like when under Dynamic DNS/IP)
$ip_addy = gethostbyname("name.dyndns.org");
WakeOnLan($ip_addy, $mac_addy,$socket_number)
?>

此脚本使我成功,但服务器无法唤醒。另外,无法指定:255.255.255.255

我还尝试在我的笔记本电脑(不是服务器)上使用数据包嗅探器,但我没有看到任何 UDP 包到达。

我尝试过的另一个脚本是这样的:

<?php
//
// ################## user variables... ##################
// Friendly name for device, example "My Computer".
$device     = "Server";
// IP address of device, example "x.x.x.x".
$deviceip   = gethostbyname("name.dyndns.org");
// TCP Port on device to check, example "3389" = RDP, "80" = WebServer.
$deviceport = "1009";
// MAC address of NIC1 on device, example "00:00:00:00:00:00" or "00-00-00-00-00-00".
$devicemac1 = "XX:XX:XX:XX:XX:XX";
// MAC address of NIC2 on device, example "00:00:00:00:00:00" or "00-00-00-00-00-00". - Optional set to "" if NIC2 not required.
$devicemac2 = "";
// Number of times to attempt to connect to port on device after magic packet sent, example "10"
$maxtries   = "5";
// Broadcast address of network, example ""x.x.x.x". ("255.255.255.255" works in most cases.)
$broadcast  = "255.255.255.255";
// ICMP port number, default "7".
$udport     = "1009";
// Timeout value for re-tries (in seconds), default "10".
$timeout    = "5";
// #######################################################
//
// ##### Read in variables from url #####
//
// $frame - used to determine which content to display when executed.
$frame      = $_GET[ "frame" ];
// $tries - used to determine number of attempts at checking port beetween reloads, compared with maxtries.
$tries      = $_GET[ "tries" ];
// $pageurl - obtain URL used to access file, used when creating frameset & setting reloads.
$pageurl    = pageurl();
// Process variables used in frame2, increments tries & sets status to Success(1) or Failed(2)
if ( $frame == 2 ) {
                processurl();
}
// ###### Functions ######
//
// function pageurl( ) - Returns URL of page via PHP variables.
function pageurl() {
  $pageurl = "HTTP";
  if ( $_SERVER[ "HTTPS" ] == "on" ) {
    $pageurl .= "S";
  }
  $pageurl .= "://";
  if ( $_SERVER[ "SERVER_PORT" ] != "80" ) {
    $pageurl .= $_SERVER[ "SERVER_NAME" ] . ":" . $_SERVER[ "SERVER_PORT" ] . $_SERVER[ "REQUEST_URI" ];
  } else {
    $pageurl .= $_SERVER[ "SERVER_NAME" ] . $_SERVER[ "REQUEST_URI" ];
  }
  $urlarts = explode( "?", $pageurl );
  $pageurl = $urlarts[ "0" ];
  return $pageurl;
}
//  function processurl( ) - Processes variables used in frame2, increments tries & sets status to Success(1) or Failed(2)
function processurl() {
  global $status, $tries, $maxtries;
  if ( $status == 0 && $tries < $maxtries - 1 ) {
    $tries = $tries + 1;
  } else {
    $status = 2;
  }
  if ( portcheck() == 0 ) {
    $status = 1;
  }
}
//  function wakeonlan() - Attempts to send WoL packet and returns outcome.
function wakeonlan( $device, $mac ) {
  global $broadcast, $udport;
  $mac            = ereg_replace( "[^A-Za-z0-9]", ":", $mac );
  $broadcast_byte = explode( ':', $mac );
  $hw_addr        = '';
  for ( $a = 0; $a < 6; $a++ )
    $hw_addr .= chr( hexdec( $broadcast_byte[ $a ] ) );
  $msg = chr( 255 ) . chr( 255 ) . chr( 255 ) . chr( 255 ) . chr( 255 ) . chr( 255 );
  for ( $a = 1; $a <= 16; $a++ )
    $msg .= $hw_addr;
  $s = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
  if ( $s == false ) {
    $content = "Error creating socket!n";
  } else {
    // setting a broadcast option to socket:
    $opt_ret = socket_set_option( $s, 1, 6, true );
    if ( $opt_ret < 0 ) {
      $content = "setsockopt() failed, error: " . strerror( $opt_ret ) . "n";
    }
    if ( socket_sendto( $s, $msg, strlen( $msg ), 0, $broadcast, $udport ) ) {
      $content = "WoL packet sent to mac address " . $mac . "...n";
      socket_close( $s );
    } else {
      $content = "Failed to send WoL packet!";
    }
  }
  return $content;
}
//  function portcheck( ) - Attempts to connect to TCP port on the device via a Socket, returns $errno.
function portcheck() {
  global $deviceip, $deviceport;
  $file = fsockopen( $deviceip, $deviceport, $errno, $errstr, 50 );
  if ( $errno == 0 ) {
    fclose( $file );
  }
  return $errno;
}
// function htmlheader( ) - Returns HTML Header for TITLE and if Frame2 REFRESH set.
function htmlheader() {
  global $device, $frame, $tries, $maxtries, $status, $pageurl, $timeout;
  // global "custom" header settings
  $content = "<TITLE>PHP WoL ($device) - by PRThomasUK </TITLE>n";
  //generate refresh header for frame2.
  if ( $frame == 2 && $status == 0 ) {
    $content .= "<META HTTP-EQUIV="refresh" CONTENT="$timeout;url=$pageurl?frame=$frame&tries=$tries">n";
  }
  return $content;
}
// function htmlheader( ) - Returns HTML content for mainpage, frame1 & frame2 based on value of $frame.
function htmlcontent() {
  global $pageurl, $device, $deviceip, $deviceport, $devicemac1, $devicemac2, $frame, $tries, $maxtries, $status;
  if ( $frame == 2 ) {
    if ( $status == 0 ) {
      $content = "<H3>$tries/$maxtries attempts to connect to $deviceip:$deviceport completed.</H3>n";
    } elseif ( $status == 1 ) {
      $content = "<FONT COLOR="green">n";
      $content .= "<H1>SUCCESS!!!</H1>n";
      $content .= "</FONT>n";
      $content .= "<H3>Connection made to $device ($deviceip:$deviceport).</H3>n";
    } else {
      $content = "<FONT COLOR="red">n";
      $content .= "<H1>FAILED...</H1>n";
      $content .= "</FONT>n";
      $content .= "<H3>Unable to connect to $device ($deviceip:$deviceport).</H3>n";
    }
  } elseif ( $frame == 1 ) {
    $content = "<FONT COLOR="navy">n";
    $content .= "<H1>PHP WoL ($device)</H1>n";
    $content .= "</FONT>n";
    $content .= wakeonlan( $device, $devicemac1 );
    if ( $devicemac2 ) {
      $content .= "<BR>n";
      $content .= wakeonlan( $device, $devicemac2 );
    }
  } else {
    $content = "<FRAMESET rows="130,*" frameborder=0 border=0 framespacing=5>n";
    $content .= "<FRAME SRC="$pageurl?frame=1">n";
    $content .= "<FRAME SRC="$pageurl?frame=2">n";
    $content .= "<NOFRAMES>n";
    $content .= "<FONT COLOR="navy">n";
    $content .= "<H1>PHP WoL ($device)</H1>n";
    $content .= "</FONT>n";
    $content .= wakeonlan( $device, $devicemac1 );
    if ( $devicemac2 ) {
      $content .= "<BR>n";
      $content .= wakeonlan( $device, $devicemac2 );
    }
    $content .= "<BR>n";
    $content .= "<BR>n";
    $content .= "<FONT COLOR="red">n";
    $content .= "<H2>Your browser does not support frames...</H2>n";
    $content .= "</FONT>n";
    $content .= "<H3>Status of $device will not be monitored!</H3>n";
    $content .= "</NOFRAMES>n";
    $content .= "</FRAMESET>n";
  }
  return $content;
}
?> 
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> 
<HTML> 
<HEAD> 
<?php
echo htmlheader();
?> 
<META NAME="author" CONTENT="PRThomasUK"> 
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=utf-8"> 
<META HTTP-EQUIV="cache-control" CONTENT="no-cache"> 
<META HTTP-EQUIV="pragma" CONTENT="no-cache"> 
<META NAME="robots" CONTENT="none"> 
<META NAME="rating" CONTENT="safe for kids"> 
</HEAD> 
<?php
echo htmlcontent();
?> 
</HTML>

这里的问题是 $deviceport = "1009"; 如果我指定 80,它会告诉我主机已关闭...但我已经知道:)这就是我正确发送魔术包的原因?...

请问有这方面的经验的人可以提供帮助吗?我没有想法可以尝试。

您应该考虑使用此简单示例脚本:

苹果电脑 :

<?php
system("/Users/usr/Downloads/wolcmd [mac] [public IP] 255.255.255.255 1009");
?>

或 Linux :

<?php
system("wakeonlan arg1 arg2 ...");
?>

要在 Debian 上安装此命令并派生:

sudo apt-get install wakeonlan

编辑 2015

好吧,我已经清理了我的流程,这非常有效:https://github.com/wearede/wake-on-wan

它现在有效!我可以通过简单地访问子域来唤醒我的服务器 wol.domain.com :)凉。

经验教训:上面的脚本无法正常工作,因为我配置了错误的路由器。从脚本中可以看出,正确的端口是 1009。在路由器上,我设置了传入端口 1009,将 wihin lan 重定向到端口 9。由于某种原因(也许是因为它是UDP?)1009->9不起作用。我做了1009->1009,服务器确实醒了!

我使用的最终代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>WOL</title>
</head>
<body>
<?php
//Creating magic packet sender function
flush();
//
function WakeOnLan($addr, $mac,$socket_number) {
  $addr_byte = explode(':', $mac);
  $hw_addr = '';
  for ($a=0; $a <6; $a++) $hw_addr .= chr(hexdec($addr_byte[$a]));
  $msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
  for ($a = 1; $a <= 16; $a++) $msg .= $hw_addr;
  // send it to the broadcast address using UDP
  $s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
  if ($s == false) {
    echo "Error creating socket!n";
    echo "Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s));
    return FALSE;
    } else {
    // setting a broadcast option to socket:
    $opt_ret = socket_set_option($s, 1, 6, TRUE);
    if($opt_ret <0) {
      echo "setsockopt() failed, error: " . strerror($opt_ret) . "n";
      return FALSE;
      }
    if(socket_sendto($s, $msg, strlen($msg), 0, $addr, $socket_number)) {
      echo "Magic Packet sent successfully!";
      socket_close($s);
      return TRUE;
      } else {
      echo "Magic packet failed!";
      return FALSE;
      }
    }
  }
                    // Port number where the computer is listening (don't forget to ope port on router!).
                    $socket_number = "1009";
                    // MAC Address of the listening computer's NIC
                    $mac_addy = "XX:XX:XX:XX:XX:XX";
                    // IP address or domain name of the listening computer.
                    $ip_addy = gethostbyname("username.dyndns.org");

//check if server is up and running
$alive = fsockopen($ip_addy, 80, $errno, $errstr, 2);   
    if (!$alive) {
        echo "<h1>Server is Down!</h1>";
        echo "I will try to turn it on now...<br />";
        //initiate wol function
        WakeOnLan($ip_addy, $mac_addy,$socket_number);
    } else {
        echo "<h1>Server is Up!</h1>";
        fclose($alive);
    }
?>
</body>
</html>