🌟
【PHP】Revolt で HTTP/2 フレームを送信する
PRI の送信だけはうまくいったが、Settings フレームを一緒に送信するとハングしてしまう
> php client.php
array(2) {
["size"]=>
int(39)
["chunk"]=>
string(78) "00001e0400000000000005001000000003000000fa000600100140000100001000000400100000"
}
array(2) {
["size"]=>
int(13)
["chunk"]=>
string(26) "000004080000000000000f0001"
}
client.php
// https://github.com/revoltphp/event-loop/blob/main/examples/http-client-async.php
use Revolt\EventLoop;
require __DIR__ . '/vendor/autoload.php';
// https://gist.github.com/masakielastic/8840124754b38663373f8f74d6f162d4
require __DIR__.'/h2frames.php';
# h2c テストサーバー
# https://zenn.dev/masakielastic/articles/530f9751697ed6
$stream = \stream_socket_client(
'tcp://localhost:8000', $errno, $errstr,
PHP_INT_MAX, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT
);
stream_set_blocking($stream, false);
EventLoop::onWritable($stream, function ($watcher, $stream) {
EventLoop::cancel($watcher);
fwrite($stream, frames('pri'));
EventLoop::onReadable($stream, function ($watcher, $stream) {
$streamId = (int) $stream;
$chunk = fread($stream, 128);
if ($chunk === '') {
EventLoop::cancel($watcher);
fclose($stream);
return;
}
dump($chunk);
EventLoop::cancel($streamId);
});
});
EventLoop::run();
strace php client.php
を実行すると pselect6
の実行で止まっていることが示される
read(5, "<?php\n\ndeclare(strict_types=1);\n"..., 1804) = 1804
close(5) = 0
pselect6(5, [4], [], [], {tv_sec=0, tv_nsec=0}, NULL) = 0 (Timeout)
pselect6(5, [4], [], [], NULL, NULL
ブロッキングな方法でも同じようにハングしてしまう
client2.php
// https://github.com/revoltphp/event-loop/blob/358572ca31647df7dbe930f13c8567136beffa33/examples/http-client-blocking.php
use Revolt\EventLoop;
require __DIR__ . '/vendor/autoload.php';
// https://gist.github.com/masakielastic/8840124754b38663373f8f74d6f162d4
require __DIR__.'/h2frames.php';
$stream = stream_socket_client('tcp://localhost:8000');
stream_set_blocking($stream, false);
fwrite($stream, h2frames('pri'));
fwrite($stream, h2frames('settings'));
$callbackId = EventLoop::onReadable($stream, function ($watcher, $stream) {
$chunk = fread($stream, 256);
if ($chunk === '') {
echo '[END]' . PHP_EOL;
EventLoop::cancel($watcher);
fclose($stream);
return;
}
dump($chunk, 'pri');
});
EventLoop::run();
EventLoop::disable($callbackId);
Discussion