ホームページ  >  記事  >  バックエンド開発  >  PHP+SocketシリーズのIO多重化とWebサーバーの実装

PHP+SocketシリーズのIO多重化とWebサーバーの実装

藏色散人
藏色散人転載
2023-02-02 13:43:363927ブラウズ

この記事では、php ソケットに関する関連知識を提供します。主に IO 多重化と、php ソケットが Web サーバーを実装する方法を紹介します。興味のある方は以下をご覧ください。皆様のお役に立てれば幸いです。

#php ネイティブ ソケット IO 多重化と Web サーバーの実装

多重化

## 前の記事

シンプルなサーバー -クライアント通信はネイティブ ソケットを介して実装されますが、複数のクライアントが接続されている場合、サーバーは最初のクライアントのリクエストのみを処理でき、後続のクライアントにはサービスを提供できません

PHP+SocketシリーズのIO多重化とWebサーバーの実装この理由IO モデルがブロックされており、同時に 1 つのクライアントしかアクセスできないという状況です。この問題を解決するには、主に 2 つの解決策があります:

    複数のプロセス、つまり複数のプロセスは、
  • IO 多重化メカニズムを監視するためにサーバー上で開始されます。これは、単純に N 個のクライアントの使用を実装します。 1 本のネットワーク ケーブルが、
  • と に同時にアクセスします。多重化は、
select

epoll という 2 つの異なるモデルに分けられます。ソフトウェアでは、Apacheselect モデルを使用し、nginxepoll モデルを使用します。 select モデルは php に組み込まれており、対応する関数は socket_select です。多重化は http サーバーを実装するための基礎です。Syntax

前の記事で、PHP のネイティブ ソケットには

select

モデルを実装する組み込みの socket_select 関数があることを紹介しました。その構文は次のとおりです: <pre class="brush:php;toolbar:false">socket_select(     array &amp;$read,     array &amp;$write,     array &amp;$except,     int $seconds [,     int $microseconds = 0]): int|false</pre>Parameters

  • read

    サーバーによって監視されるソケット リソース (つまり、新しいメッセージが受信されたとき、またはクライアントが変更されたとき)接続または切断されています)、

    socket_select

    関数は戻ります (そうでない場合はブロックを続けます)、同時に変数を現在のイベント (受信したメッセージまたはクライアント接続、または切断)、下方向に実行を続けます。

  • write

    #データを書き込んでいるクライアントがあるかどうかを監視します。

    null

    を渡すことは、データを書き込んでいないことを意味します。書き込み変更があるかどうかに注意してください。

  • Except

    ソケット内で除外される要素。

    null

    を渡します。すべてを「リッスン」しています

  • 秒とマイクロ秒を合わせてタイムアウト パラメータを形成します。

    null

    を渡すとブロック、0 を渡すとノンブロッキング、>0 を渡すと最大ブロック時間

  • マイクロ秒

  • 最適化

#前回の記事

では、ソケットのサーバー側監視接続を実装しただけです。次に、サーバー側の監視コードの基礎を構築します。多重化を通じてコードを最適化します:

<?php

// 创建套接字
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

// 设置 ip 被释放后立即可使用
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, true);

// 绑定ip与端口
socket_bind($socket, 0, 8888);

// 开始监听
socket_listen($socket);

$sockets[] = $socket;

while (true) {
    $tmp_sockets = $sockets;
    socket_select($tmp_sockets, $write, $except, null);

    foreach ($tmp_sockets as $sock) {
        // 如果当前套接字等于 socket_create 创建的套接字,说明是有新的连接或有新的断开连接
        if ($sock == $socket) {
            $conn_sock = socket_accept($socket);
            $sockets[] = $conn_sock;
            socket_getpeername($conn_sock, $ip, $port);
            echo &#39;请求ip: &#39; . $ip . &#39;端口: &#39; . $port . PHP_EOL;
        } else { // 否则说明是之前连接的客户端发来消息
            $msg = socket_read($sock, 10240);
            socket_write($sock, strtoupper($msg));
            echo $msg;
        }
    }
}
この例では、socket_select

関数が現在のプロセスをブロックします。配列内の

$tmp_sockets ソケット リソースが新しい場合、クライアントが接続または切断するか、新しいメッセージを受信すると、$tmp_sockets 配列を現在アクティブなソケット リソースに変更します。次に、配列を走査してビジネス ロジックを処理します

PHP+SocketシリーズのIO多重化とWebサーバーの実装ソケットを使用して単純な http サーバーを実装します

http プロトコルは指定されたデータを指定します形式はソケットに基づいているため、必要なのは socket_write

形式に従ってデータを送信すると、ブラウザは通常どおりリクエストに応答できます

<?php

// 创建套接字
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

// 设置 ip 被释放后立即可使用
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, true);

// 绑定ip与端口
socket_bind($socket, 0, 8888);

// 开始监听
socket_listen($socket);

$sockets[] = $socket;

while (true) {
    $tmp_sockets = $sockets;
    socket_select($tmp_sockets, $write, $except, null);

    foreach ($tmp_sockets as $sock) {
        if ($sock == $socket) {
            $conn_sock = socket_accept($socket);
            $sockets[] = $conn_sock;
        } else {
            $msg = socket_read($sock, 10240);
            var_dump($msg);
            if ($msg == &#39;&#39;) return;

            $output = &#39;<h1>this is php worker</h1>&#39;;
            $len = strlen($output);

            $response = "HTTP/1.1 200 OK\r\n";
            $response .= "content-type: text/html\r\n";
            $response .= "server: php socket\r\n";
            $response .= "Content-Length: {$len}\r\n\r\n";

            $response .= $output;

            socket_write($sock, $response);
        }
    }
}
この例をサーバー上で実行し、アクセスしますip:8888

をブラウザに表示すると、次の内容が表示されます:

同時に、サーバーは次の内容を出力します: PHP+SocketシリーズのIO多重化とWebサーバーの実装

GET / HTTP/1.1
Host: 124.222.**.**:8888
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: jenkins-timestamper-offset=-28800000; _ga=GA1.1.1403944751.1652010033; _ga_2GM6102E19=GS1.1.1652802985.7.1.1652803014.0

このコンテンツはユーザーによって要求された元のデータであり、ユーザーはこのデータを解析し、

file_get_content

を使用するなどの要求に従って応答できます。指定されたファイルのコンテンツを読み取り、ブラウザーに返します。

推奨学習: 「

PHP ビデオ チュートリアル

##

以上がPHP+SocketシリーズのIO多重化とWebサーバーの実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlearnku.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。