【PHP】PHPでWebSocketサーバー - クライアント・サーバー間通信 -

前回の記事でPHPにより実装したWebSocketサーバーを介してのクライアント間通信を実装しました。

今回はサーバー側から一方的にクライアントへメッセージを送信してみたいと思います。

使用するライブラリは以下を使用しましたが、結果を先に言ってしまうとelephant.ioのほうはうまく行きませんでした。以下にその手順と結果を残しておきます。

  • wisembly/elephant.io
  • textalk/websocket

サーバーからメッセージ送信 (wisembly/elephant.io)

ライブラリのインストール

composer.json

composer.json の require に以下を追加

"wisembly/elephant.io":"~3.0"

以下コマンドでインストール

$ ./composer.phar update --lock

Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing wisembly/elephant.io (v3.3.1): Loading from cache
Package guzzle/common is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Package guzzle/http is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Package guzzle/parser is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Package guzzle/stream is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Writing lock file
Generating autoload files

サーバー側実装

websocket_test/emit.php

ネット記事を参考にしながら以下の送信スクリプトを作成しました。(requireのパスは適時)

<?php
use ElephantIO\Client;
use ElephantIO\Engine\SocketIO\Version1X;

require __DIR__.'/../fuel/vendor/autoload.php';

$client = new Client(new Version1X("ws://localhost:9000"));
$client->initialize();
$client->emit("message", "from server");

動作確認

送信スクリプト実行

$ php websocket_test/emit.php
Fatal error: Uncaught ElephantIO\Exception\ServerConnectionFailureException:
An error occurred while trying to establish a connection to the server in
fuel/vendor/wisembly/elephant.io/src/Engine/SocketIO/Version1X.php:187 Stack trace: #0 fuel/vendor/wisembly/elephant.io/src/Engine/SocketIO/Version1X.php(48):
ElephantIO\Engine\SocketIO\Version1X->handshake() #1 fuel/vendor/wisembly/elephant.io/src/Client.php(60):
ElephantIO\Engine\SocketIO\Version1X->connect() #2 websocket_test/emit.php(8): ElephantIO\Client->initialize() #3 {main} thrown in fuel/vendor/wisembly/elephant.io/src/Engine/SocketIO/Version1X.php on line 187

initialize() で落ちます。落ちている箇所は Version1X->handshake メソッドで、WebSocketサーバーとの接続に失敗しているようです。

エラー内容

エラー内容をデバッグしたところ以下のようになっています。

array(4) {
  ["type"]=>
  int(2)
  ["message"]=>
  string(157) "file_get_contents(ws://localhost:9000/socket.io/?use_b64=0&EIO=2&transport=polling):
 failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request
"
  ["file"]=>
  string(97) "fuel/vendor/wisembly/elephant.io/src/Engine/SocketIO/Version1X.php"
  ["line"]=>
  int(179)
}

file_get_contents でWebSocketサーバーに接続を試みたところ 400 Badrequest が返ってきているようですが原因がわかりません。URLを変えたり色々試しましたができませんでした。

WebSocketサーバーをPHPで実装しているためかもしれません(根拠はありません)

結局今だに解決には至っておらず、別の方法を探して textalk/websocket を使う方法にたどり着きました。

サーバーからメッセージ送信 (textalk/websocket)

textalk/websocket を使用してサーバーからメッセージを送信する方法です。

ライブラリのインストール

composer.json

require に以下を追加します。

"textalk/websocket":"1.0.*"

以下コマンドでインストール

$ ./composer.phar update --lock

Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing textalk/websocket (1.0.3): Loading from cache
Package guzzle/common is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Package guzzle/http is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Package guzzle/parser is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Package guzzle/stream is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Writing lock file
Generating autoload files

サーバー側実装

websocket_test/send.php

ここでもネット記事を参考にしながら以下のスクリプトを作成しました。(requireのパスは適時)

<?php
require __DIR__.'/../fuel/vendor/autoload.php';

use WebSocket\Client;

$client = new Client("ws://localhost:9000");
$client->send("from server");

動作確認

$ php websocket_test/send.php

これでクライアントへメッセージが届きました。

Jsonオブジェクトで渡してやれば様々な情報を送ることができそうです。

コメント

このブログの人気の投稿

docker-compose up で proxyconnect tcp: dial tcp: lookup proxy.example.com: no such host

docker-compose で起動したweb、MySQLに接続できない事象

【PHP】PHP_CodeSnifferを使う(コーディングルールのカスタマイズ)