まず、スレッドセーフティフラグを使用してコンパイルされたPHPアセンブリが必要です。 作業にはWindowsを使用しているため、完成したパッケージをここからダウンロードしました 。 OSの正しいビット深度、PHPの目的のバージョン、そしてもちろん、スレッドセーフバージョンを選択するだけです。 記事全体を通して、PHPを使用してアーカイブをC:\ phpディレクトリに解凍したと想定されます。 次に、pthreads拡張機能をインストールする必要があります。 ここに行き、ダウンロードしたPHPのバージョンとシステムの容量に対応するバージョンを選択します。 アーカイブから、php_pthreads.dllファイルをC:\ php \ extディレクトリにコピーし、pthreadVC2.dllファイルをC:\ phpおよびC:\ Windows \ System32ディレクトリにコピーします。 C:\ phpディレクトリで、php.ini-developmentファイルの名前をphp.iniに変更し、次の行を追加します。
extension=php_pthreads.dll
また、extension_dirディレクティブを見つけて解凍し、「C:\ php \ ext」に設定します(PHP7のバージョンでは、相対パスは機能しませんでした)。 コマンドラインを開き、次を確認します。
C:\php\php.exe -v
出力の最初の行の最後に、マーク(ZTS)が表示されます。 サーバー実装に直接渡します。 ファイルを作成します(私の場合、C:\ server.phpにあります。まず、ローカルマシンのポート8080でリッスンするソケットを作成します。
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_bind($server, '127.0.0.1', 8080); socket_listen($server);
次に、ワーカーのプールを作成します。
$pool = new Pool(10, Worker::class);
最初の引数はアクティブなスレッドの最大数を設定し、2番目はワーカーのクラス名です。 より具体的なタスクについては、Workerクラスから継承してクラスを説明できます。 元のクラスを使用します。 今後、スレッドクラスでは、$ this-> workerを使用してインストール済みワーカーを取得できると言います。
次に、別のスレッドで実行されるクラスを実装します。 クラスはThreadedから継承する必要があります。
class Task extends Threaded { protected $socket; public function __construct($socket) { $this->socket = $socket; } public function run() { if (!empty($this->socket)) { $response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 12\r\n\r\nHello world!"; socket_write($this->socket, $response, strlen($response)); // zend_mm_heap currupted, //socket_close($this->socket); } } }
このクラスは、コンストラクターでクライアント接続ソケットを受け入れます。 また、ストリームで実行されるアクションは、run()メソッドで記述する必要があります。 私の場合、これはベースヘッダーとテキスト「Hello world!」を含むクライアントへの回答です。
次に、クライアントからの接続を周期的に受け入れ、成功した場合は別のストリームを作成し、そこにソケット記述子を渡します。
$servers = [$server]; while (true) { $read = $servers; if (socket_select($read, $write, $except, 0) >= 0 && in_array($server, $read)) { $task = new Task(socket_accept($server)); $pool->submit($task); } }
無限ループを使用するため、スクリプトが完了してプールを停止したときに実行される関数を登録します。 関数は、サイクルの開始前に登録する必要があります。
register_shutdown_function(function () use ($server, $pool) { if (!empty($server)) { socket_close($server); } $pool->shutdown(); });
実際にはすべて。 コマンドラインでサーバーを起動し、ブラウザーでlocalhost :8080を開きます。
cd C:\ C:\php\php.exe server.php
以下は完全なサーバーコードです。
<?php $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_bind($server, '127.0.0.1', 8080); socket_listen($server); $pool = new Pool(10, Worker::class); class Task extends Threaded { protected $socket; public function __construct($socket) { $this->socket = $socket; } public function run() { if (!empty($this->socket)) { $response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 12\r\n\r\nHello world!"; socket_write($this->socket, $response, strlen($response)); } } } register_shutdown_function(function () use ($server, $pool) { if (!empty($server)) { socket_close($server); } $pool->shutdown(); }); $servers = [$server]; while (true) { $read = $servers; if (socket_select($read, $write, $except, 0) >= 0 && in_array($server, $read)) { $task = new Task(socket_accept($server)); $pool->submit($task); } }
ご清聴ありがとうございました!