PHP IRC Bot创建无限循环

时间:2014-07-18 23:44:16

标签: php irc

Stack Overflow的开发人员大家好!我最近重新开始进行Web开发(虽然我以前不太擅长),PHP是我的首选武器。自从我离开之后,PHP似乎已经发生了变化,并将其与我从未使用过PHP套接字这一事实相结合,然后导致了灾难性的第一次创建IRC机器人的尝试(我在IRC频道上,机器人开发很大,我想将它集成到我的网站。在php中编写它似乎也是一个有趣的挑战)。它创建了一个无限循环,使我的浏览器变慢,我无法复制任何错误或警告。好心人会这么想看这个脚本(基于这个bot):

<!DOCTYPE html>
<html lang="en-US">
    <head>
        <title>Lucky Cloud</title>
    </head>

    <body>
        <?php
            error_reporting(E_ERROR);

            $bot = array(
                            "Host"     => "irc.quakenet.org",
                            "Channels" => ["#cplusplus", "#BotDevGroundZero"],
                            "Nick"     => "LuckyCloud",
                            "Ident"    => "LuckyCloud",
                            "Real"     => "LuckyCloud",
                            "Port"     => 6667
                   );
            $buffer = "";
        ?>

        <p>
            Server: <?php echo $bot["Host"]; ?><br />
            Channel(s): <?php foreach($bot["Channels"] as $channel) echo $channel.($channel != end($bot["Channels"]) ? ", " : ""); ?><br />
            Port: <? echo $bot["Port"]; ?><br />
            ___________________________________________________________________________________________________________________<br />
        </p>

        <?php
            global $socket;
            $socket = fsockopen($bot["host"], $bot["Port"]);

            function sendData($cmd, $msg = null) {
                if($msg == null) {
                    fputs($socket, $cmd."\r\n");
                    echo "<strong>".$cmd."</strong><br />";
                }

                else {
                    fputs($socket, $cmd." ".$msg."\r\n");
                    echo "<strong>".$cmd." ".$msg."</strong><br />";
                }
            }

            sendData("NICK", $bot["Nick"]);
            sendData("USER", $bot["Ident"]." ".$bot["Host"]." ".$bot["Real"]);

            $buffer = "";

            while(true) {
                foreach($bot["Channels"] as $channel) {
                    sendData("JOIN", $channel);
                }

                $buffer += fgets($socket, 1024);
                $temp = explode("\n", $buffer);
                $buffer = end($temp);

                foreach($temp as $line) {
                    echo $line;
                    $line = rtrim($line);
                    $line = explode($line);

                    if($line[0] == "PING") {
                        sendData("PONG", $line[1]);
                    }
                }
            }
        ?>
    </body>
</html>

抱歉任何格式问题。 cpanel编辑器表现得很奇怪

2 个答案:

答案 0 :(得分:2)

你无法以这种方式实现它,导致问题的原因很简单,一旦while(true)循环启动它就不会停止。

您需要将请求与处理循环分开。所以将循环作为后台进程(守护进程),然后通过另一个接口(例如threads数据库)将PINGS和PONGS等推送到它,然后在循环的每次迭代中,查询数据库中的PINGS和PONGS。

答案 1 :(得分:0)

PHP不是这项工作的最佳选择。保持长时间连接并不是很好。此脚本可能用于短时联接,您只需删除邮件并离开即可。类似“基于事件的通知”。

您的脚本的几个补充:

  • 时区
  • error_reporting并显示
  • timelimit 0
  • 修改为while (!feof($socket)) {
  • PING / PONG:由substr
  • 替换爆炸
  • 这连接到freenode,quakenet是一个婊子 - 这里需要更多魔法:)
  • JOIN在WHILE内部,但我们只需要一次 - 后卫添加
  • 在频道内观看连接
  • 输出没有刷新......嗯..

<html lang="en-US">
<head>
    <title>Lucky Cloud</title>
</head>  
<body>
    <?php
        date_default_timezone_set('America/Los_Angeles');
        error_reporting(E_ALL);
        ini_set("display_errors", 1);
        set_time_limit(0);

        $bot = array(
            "Host"     => "kornbluth.freenode.net", #"underworld2.no.quakenet.org", #irc.quakenet.org",
            "Channels" => ["#testerchan"],
            "Nick"     => "Tester7888",
            "Ident"    => "Tester7888",
            "Real"     => "Susi Q",
            "Port"     => 6667
        );
    ?>

    <p>
        Server: <?php echo $bot["Host"]; ?><br />
        Channel(s): <?php foreach($bot["Channels"] as $key => $channel) { echo $channel; } ?><br />
        Port: <?php echo $bot["Port"]; ?><br />
        ___________________________________________________________________________________________________________________<br />
    </p>

    <?php
        global $socket;

        function sendData($cmd, $msg = null) {
            global $socket;
            if($msg == null) {
                fputs($socket, $cmd."\r\n");
                echo "<strong>".$cmd."</strong><br />";
            } else {
                fputs($socket, $cmd." ".$msg."\r\n");
                echo "<strong>".$cmd." ".$msg."</strong><br />";
            }
        }

        $socket = fsockopen($bot["Host"], $bot["Port"], $error1, $error2);
        if(!$socket) {
            echo 'Crap! fsockopen failed. Details: ' . $error1 . ': ' . $error2;
        }

        sendData("NICK", $bot["Nick"]);
        sendData("USER", $bot["Ident"]." ".$bot["Host"]." ".$bot["Real"]);

        $join_at_start = true;

        $buffer = "";

        while (!feof($socket)) {
            $buffer = trim(fgets($socket, 128));
            echo date('H:i')." ".nl2br($buffer)."<br/>";
            flush();

            # Ping <-> Pong
            if(substr($buffer, 0, 6) == "PING :") {
                fputs($socket, "PONG :".substr($buffer, 6)."\r\n");
                echo $buffer;
                flush();
            }

            // break out of while, 0 bytes
           /* $stream_meta_data = stream_get_meta_data($socket);
            if($stream_meta_data['unread_bytes'] <= 0) {
                break;
            }*/

            # join only one time
            if($join_at_start === true && false === strpos($buffer, 'Your host is trying to (re)connect too fast -- throttled')) {
                foreach($bot["Channels"] as $key => $channel) {
                   sendData("JOIN", $channel);
                   $join_at_start = false;
                }
            }
        }
    ?>
</body>