【问题标题】:PHP - IRC Bot Script HangingPHP - IRC Bot 脚本挂起
【发布时间】:2011-05-12 21:56:17
【问题描述】:

我的 IRC Bot 脚本有问题,我已将它实现到我的 Curl 传输方法中。

我有一个问题,一旦 IRC 机器人向 IRC 频道发送消息,脚本末尾的所有“回声”都不会显示并且页面会挂起。整个 Apache 挂起。

<?php

$ircServer = "///";
$ircPort = "6667";
$ircChannel = "#bots";

set_time_limit(0);

$msg = $_POST['msg'];
$paper = $_POST['paper'];
$sizzor = $_POST['sizzor'];
$hand = $_POST['hand'];

$ircSocket = fsockopen($ircServer, $ircPort, $eN, $eS);

if ($ircSocket)
{

    fwrite($ircSocket, "USER Lost rawr.test lol :code\n");
    fwrite($ircSocket, "NICK Rawr" . rand() . "\n");
    fwrite($ircSocket, "JOIN " . $ircChannel . "\n");

ignore_user_abort(TRUE); // Noob Close down page

    fwrite($ircSocket, "PRIVMSG " . $ircChannel . " :" . $msg . "\n");

    while(1)
    {
        while($data = fgets($ircSocket, 128))
        {
            echo nl2br($data);
            flush();

            // Separate all data
            $exData = explode(' ', $data);

            // Send PONG back to the server
            if($exData[0] == "PING")
            {
                fwrite($ircSocket, "PONG ".$exData[1]."\n");
            }
}
    echo $eS . ": " . $eN;
}
}
?>
if ($bootcontents == 'success') {     
 echo '<center><marquee behavior="alternate" direction="left">Spinning xxx at ' . $power . '% power.</marquee></center>';

这部分在脚本中不显示:

if ($bootcontents == 'success') { 
    echo '<center><marquee behavior="alternate" direction="left">Spinning xxx at ' . $power . '% power.</marquee></center>';

页面只是挂起,如果我将exit(); 函数添加到顶部附近,整个“回声”信息不会显示。

请有人帮忙。

【问题讨论】:

  • 我看到你有一个循环:while(1)。如果你没有终止条件来跳出这个循环,那将是一个无限循环。
  • 通过网络服务器启动这样的东西是不好的。此外,理智的服务器不会让您的机器人发送任何消息,因为它没有响应可能在收到 USER 和 NICK 后立即发送的 PING。
  • 您必须从命令行运行您的机器人,而不是通过网页。

标签: php bots irc


【解决方案1】:

你正在创建一个无限循环:

while (1)
// ...

这个循环永远不会结束,因为你没有使用退出语句(比如break)。因此,无限循环之后的代码永远不会执行。 此外,它是一个繁忙的循环(使用大量 CPU 资源),所以整个 apache(和计算机)都会挂起。

【讨论】:

  • 脚本旨在无限运行,这是设计使然。可能这就是为什么您看到反对票的原因。从代码中可以明显看出这是故意的。当然,给出的解释是失败 OP 的一部分。所以你会得到反对票。
  • hakre... OP 的意图是有一个无限循环来捕获服务器输出,但他的设计是完全错误的...并回答 OP 的问题,即为什么 echo 永远不会以上述 2 个回复运行完全有效,因为他从未询问过他的设计,但为什么这部分代码不起作用。所以我们可以忽略他的设计意图并评论代码本身。
【解决方案2】:

您在&lt;?php ?&gt; 标记之外留下了一些行,因此它们之外的任何内容都将被视为纯文本。您修复它,将关闭的?&gt; 标签进一步向下移动:

        [this is the while(1) closing bracket]
        }
    // code past this line will never run, see below for details
    echo $eS . ": " . $eN;
    }
}
if ($bootcontents == 'success') {
  echo '<center><marquee behavior="alternate" direction="left">Spinning xxx at ' . $power . '% power.</marquee></center>';
}
?> <!-- closing tag goes here -->

页面无论如何无法正常工作,因为while(1) 循环缺少退出条件:

while(1) {
    while($data = fgets($ircSocket, 128)) {
      // ...
    }
}

内部while 完成后,您的脚本继续循环,最终陷入一个空的无限循环(如果未配置为检测并杀死此类漏洞,这将挂起服务器)。

最后一点,PHP 可能不是完成这项工作的最佳工具:使用独立应用程序会更好。

【讨论】:

    【解决方案3】:
    while($data = fgets($ircSocket, 128))
    

    这部分会阻止脚本运行,直到它接收到数据,如果不知何故你没有通过那个套接字获取数据……那么你就卡在那里……永远……哈哈,好吧,一直卡到 PHP 脚本超时。

    如果该部分没有捕获,您仍然被困在 while 循环中,因此无法运行代码中回显内容的部分......所以 apfelbox 和 Alex 都是正确的,只是没有解释清楚...

    为了有一个无限循环但也能够在外部运行代码,您需要捕获要捕获和运行代码的“事件”。您要捕获的所有事件都需要位于 while 循环内,或者至少从 while 循环分派到一个函数,该函数将解析来自服务器的输入并正确响应。

    更好的方法是利用观察者模式。

    我真的不会用 PHP 制作一个 IRC 机器人,即使你通过命令行运行它... PHP 并不意味着作为一个长时间运行的应用程序运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-19
      • 2012-10-04
      • 1970-01-01
      • 1970-01-01
      • 2015-03-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      相关资源
      最近更新 更多