仕事の ejabberd 認証を取得するために 1 日を費やしました。
基本的に、標準入力からの読み取り中にプロセスをブロックすると問題が発生します。クライアントがタイムアウトのために切断されるまで、リクエスト文字列の最後でブロックされたままになります。
記述子からのシンボル読み取りによる非ブロックシンボルの解決策は次のとおりです。
function non_block_read($fd, &$data) {
$read = array($fd);
$write = array();
$except = array();
$result = stream_select($read, $write, $except, 0);
if($result === false) {
throw new Exception('stream_select failed');
}
if($result === 0) return false;
$data.= stream_get_line($fd, 1);
return true;
}
これは、生涯読み取りサイクルを作成するためのデーモン コードです。
$fh = fopen("php://stdin", 'r');
$fhout = fopen("php://stdout", 'w');
$pdo = new PDO('mysql:host='.$host.';dbname='.$db, $user,$pass);
if(!$fh){
die("Cannot open STDIN\n");
}
$aStr='';
$collect=false;
do {
if (!non_block_read($fh,$aStr)) {
if (strlen($aStr) > 0) {
$toAuth = substr(trim($aStr),1);
checkAuth($toAuth,$pdo,$fhout);
$aStr='';
}
else sleep (1);
}
}
while (true);
いくつかの説明: checkAuth - 'auth' および 'isuser' ハンドラーを実装する任意の関数。
sleep(1) - CPU 負荷を回避する簡単な方法。
最初の記号 - メッセージの先頭に追加するサービス記号で、クライアントごとに異なるため、切り取っただけです。
これが応答コードです。返信 - 真 | 偽の値。
$message = @pack("nn", 2, $result);
fwrite($stdout, $message);
flush();
楽しみ。