1

いくつかのチュートリアルに従ってボットをゼロから作成すると、基本的な機能は正常に機能し、接続でき、コマンドに応答し、Web ページに出力されます。

私が欲しいのは、curl を使用して Web サイトから取得しているチャネルに更新を含むメッセージを定期的に送信することです。

$irc と $curl は設定を含む単なる配列であり、date('s') は更新を返す関数と言えます。もちろん、そのためにカール機能が働いています。$irc['delay'] は 10 に設定されているため、sleep(1) では 10 秒ごとに更新を送信する必要があります。

問題は、最初の 1 分間ほど、現在の秒数を 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 が
断りなく提案したように、日付を 1 回言うと、次のレポートまで少なくとも 1 分かかります。私が何かコマンドを言うと、それはさらに遅れます。

10:39 モニナル 来ました
10:39 モニナル 39:24
10:40 モニナル 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 モニナル 42:51

2 番目のメッセージを送信した後、初めて Web ページに出力が表示され、次のレポートはすべて 10 秒ではなく 61 秒ごとに送信されます。

10:42 モニナル 42:51
10:43 モニナル 43:52
10:44 モニナル 44:53

内側のループにブレークを追加すると: 最初の 1 分間は 10 秒ごとにレポートを取得しますが、以前と同様に、送信されたすべてのコマンドは最初の 1 分間の終わりにトリガーされます。その後、コマンドは機能しますが、再び 61 秒ごとに報告されます。

多分それは私のサーバー設定に何かありますか?

4

2 に答える 2

0

苦しみの一日の後、私はついにばかげた理由と解決策を見つけました. 基本的に、1 分の遅延の理由は fget コマンド while($data = fgets($socket, 128)); です。
回避策は、stream_set_timeout($socket,1); を設定することです。ループ前。さて、Apacheの代わりにnginxサーバーをセットアップすることにもなりました。とにかくそれが役立つかどうかはわかりません。
また、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 に答える
0

while($data = fgets($socket, 128))問題は、ループ内にすべてのロジックがあることだと思います。考えてみると、チャットで何かが起こっている場合にロジックが実行されます。したがって、スクリプトを開始すると、そこにあったデータを読み取るため (そうすると思います)、正常に実行されますが、そのデータが読み取られた後は、新しいデータに対してのみ実行されます。

内部の while ループ条件が常に true の場合 (毎秒実行される場合) にのみ 10 秒になるため、128 バイトの 10 回 (つまり 10 秒) 待機するため、チャットに秒のみを出力するようになりました。

ロジックの一部を内側の while ループの外に移動してみてください。また、カールのタイミングを変更しました-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秒に1回ではなく、すべてのコマンドに同時に応答する可能性があります。これを変更したい場合は、内側のwhileの最後にブレークを追加してみてください。

于 2013-03-12T06:00:26.870 に答える