1

我按照一些教程从头开始创建机器人,基本功能工作正常,比如我可以连接,它响应命令,并将输出输出到网页。

我想要的是定期向频道发送消息,这些消息是我从某个带有 curl 的网站获得的。

$irc 和 $curl 只是带有设置的数组,而 date('s') 可以说是返回更新的函数。当然,我有为此工作的 curl 功能。$irc['delay'] 设置为 10,因此使用 sleep(1) 它应该每 10 秒发送一次更新。

问题是在第一分钟左右,它每 10 秒发送一次当前秒数,但它不听我设置的任何命令。它在第一个初始延迟之后执行命令,我不是它来自的地方
然后它仅在有人在频道上讲话时才向当前秒数(if 条件)发送消息。我猜它在等待这 128 个字节?但它确实会立即听命令。

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

        if ($curl['delay'] <= $d) { fputs($socket, "PRIVMSG ".$irc['channel']." :".date('s')."\n"); $d=0; };
        $d+=1;
        sleep(1);

        $ex = explode(' ', $data);
        if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."\n");
        $command = str_replace(array(chr(10), chr(13)), '', $ex[3]);
        switch ($command) {
            case ":!say" : fputs($socket, "PRIVMSG ".$ex[2]." :Hello!\n"); break;
            case ":!off" : break 3;
        };
    };
}

好吧,我希望它既响应命令,又定期自动发送消息提取数据。但我不明白它的行为,甚至不知道我想要什么是可能的 php



就像 Ranty 建议的那样
:它会说一次日期,然后下一次报告至少需要一分钟。如果我说任何命令,它会进一步延迟它。

10:39 Moninal 我来了
10:39 Moninal 39:24
10:40 Moninal 40:26

10:41 Moninal 我来了
10:41 Moninal 41:05
10:41 Gregos !sayit
10:41 Moninal 你好!
10:41 Gregos !sayit
10:41 Moninal 你好!
10:42 Moninal 42:51

在它发送第二条消息后,我第一次在网页上得到输出,下一个报告每 61 秒发送一次,而不是 10 秒。

10:42 莫纳尔 42:51
10:43 莫纳尔 43:52
10:44 莫纳尔 44:53

如果我在内部循环中添加中断:对于第一分钟,我每 10 秒收到一次报告,但所有发送的命令都在第一分钟结束时触发,就像以前一样。在那之后,命令起作用,但每 61 秒再次报告一次。

也许这与我的服务器配置有关?

4

2 回答 2

0

我想问题是你在while($data = fgets($socket, 128))循环中拥有所有逻辑。如果您考虑一下,如果聊天中发生了某些事情,就会执行您的逻辑。因此,当您启动脚本时,它执行正常,因为它读取那里的数据(我假设是这样),但是在读取该数据之后,它只在新数据上执行。

现在它只在聊天中打印秒数,因为它等待 10 次 128 字节(你的意思是 10 秒),因为只有当内部 while 循环条件始终为真(如果它每秒执行一次)时,它才会是 10 秒。

您可以尝试将一些逻辑移到内部 while 循环之外。我还为您更改了 curl 时间 - 让它休眠 1 秒并在计数器上加 1 的方式 - 这是不可靠的。您可以简单地将当前时间与上次请求的时间进行比较。

while(1) {
    flush();

    if ($curl['next_request'] <= time()) {
        fputs($socket, "PRIVMSG ".$irc['channel']." :".date('s')."\n");
        $curl['next_request'] = time() + $curl['delay'];
    };

    while($data = fgets($socket, 128)) {
        echo nl2br($data);
        $ex = explode(' ', $data);
        if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."\n");
        $command = str_replace(array(chr(10), chr(13)), '', $ex[3]);
        switch ($command) {
            case ":!say" : fputs($socket, "PRIVMSG ".$ex[2]." :Hello!\n"); break;
            case ":!off" : break 3;
        };
    };

    sleep(1);
}

它可能会同时响应所有命令,而不是每秒 1 个,如果你想改变它,你可以尝试在内部 while 的末尾添加一个 break。

于 2013-03-12T06:00:26.870 回答
0

好吧,经过一天的痛苦,我终于找到了愚蠢的原因和解决方案。基本上延迟 1 分钟的原因是 fget 命令 while($data = fgets($socket, 128));
解决方法是设置 stream_set_timeout($socket,1); 在循环之前。好吧,我也最终设置了 nginx 服务器而不是 apache。我不确定这是否有帮助。
另外我想我可以在 stream_set_timeout($socket,1); 中设置时间 控制发送消息的最小间隔。

$next=time();
stream_set_timeout($socket,1);
while(1) {

    $data = fgets($socket, 128);
    echo nl2br($data);

    $ex = explode(' ', $data);
    if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."\n");
    if (isset($ex[3])) $command = str_replace(array(chr(10), chr(13)), '', $ex[3]);

    switch ($command) {
        case ":!sayit" : 
            $msg = NULL; for ($i = 4; $i < count($ex); $i++) { $msg .= $ex[$i] . ' '; }
            fputs($socket, "PRIVMSG ".$ex[2]." :".$msg."\n"); 
            break;
        case ":!off" :
          fputs($socket, "PRIVMSG ".$irc['channel']." : Bye\n");
          fputs($socket,"QUIT Client Disconnected!\n");
          die('Exited!');
    };

    if ($next <= time()) {
        fputs($socket, "PRIVMSG ".$irc['channel']." :".date('H:i:s')."\n");
        echo "PRIVMSG ".$irc['channel']." :".date('H:i:s')."<br />";
        $next = time() + $curl['delay']; 
    };
    flush(); 
};

好吧,它不包括所有的连接设置。这很容易找到怎么做。

于 2013-03-12T16:34:15.677 回答