14-http-client-async.php 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. <?php
  2. use React\EventLoop\Factory;
  3. use React\EventLoop\Loop;
  4. require __DIR__ . '/../vendor/autoload.php';
  5. // resolve hostname before establishing TCP/IP connection (resolving DNS is still blocking here)
  6. // for illustration purposes only, should use react/socket or react/dns instead!
  7. $ip = gethostbyname('example.com');
  8. if (ip2long($ip) === false) {
  9. echo 'Unable to resolve hostname' . PHP_EOL;
  10. exit(1);
  11. }
  12. // establish TCP/IP connection (non-blocking)
  13. // for illustraction purposes only, should use react/socket instead!
  14. $stream = stream_socket_client('tcp://' . $ip . ':80', $errno, $errstr, null, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT);
  15. if (!$stream) {
  16. exit(1);
  17. }
  18. stream_set_blocking($stream, false);
  19. // print progress every 10ms
  20. echo 'Connecting';
  21. $timer = Loop::addPeriodicTimer(0.01, function () {
  22. echo '.';
  23. });
  24. // wait for connection success/error
  25. Loop::addWriteStream($stream, function ($stream) use ($timer) {
  26. Loop::removeWriteStream($stream);
  27. Loop::cancelTimer($timer);
  28. // check for socket error (connection rejected)
  29. if (stream_socket_get_name($stream, true) === false) {
  30. echo '[unable to connect]' . PHP_EOL;
  31. exit(1);
  32. } else {
  33. echo '[connected]' . PHP_EOL;
  34. }
  35. // send HTTP request
  36. fwrite($stream, "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n");
  37. // wait for HTTP response
  38. Loop::addReadStream($stream, function ($stream) {
  39. $chunk = fread($stream, 64 * 1024);
  40. // reading nothing means we reached EOF
  41. if ($chunk === '') {
  42. echo '[END]' . PHP_EOL;
  43. Loop::removeReadStream($stream);
  44. fclose($stream);
  45. return;
  46. }
  47. echo $chunk;
  48. });
  49. });