この記事では、php ソケットに関する関連知識を提供します。主に IO 多重化と、php ソケットが Web サーバーを実装する方法を紹介します。興味のある方は以下をご覧ください。皆様のお役に立てれば幸いです。
多重化
## 前の記事シンプルなサーバー -クライアント通信はネイティブ ソケットを介して実装されますが、複数のクライアントが接続されている場合、サーバーは最初のクライアントのリクエストのみを処理でき、後続のクライアントにはサービスを提供できません
この理由IO モデルがブロックされており、同時に 1 つのクライアントしかアクセスできないという状況です。この問題を解決するには、主に 2 つの解決策があります:
と epoll
という 2 つの異なるモデルに分けられます。ソフトウェアでは、Apache
は select
モデルを使用し、nginx
は epoll
モデルを使用します。 select
モデルは php に組み込まれており、対応する関数は socket_select
です。多重化は http サーバーを実装するための基礎です。Syntax
モデルを実装する組み込みの socket_select
関数があることを紹介しました。その構文は次のとおりです: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">socket_select(
array &$read,
array &$write,
array &$except,
int $seconds [,
int $microseconds = 0]): int|false</pre><div class="contentsignin">ログイン後にコピー</div></div>
Parameters
サーバーによって監視されるソケット リソース (つまり、新しいメッセージが受信されたとき、またはクライアントが変更されたとき)接続または切断されています)、
関数は戻ります (そうでない場合はブロックを続けます)、同時に変数を現在のイベント (受信したメッセージまたはクライアント接続、または切断)、下方向に実行を続けます。
#データを書き込んでいるクライアントがあるかどうかを監視します。
を渡すことは、データを書き込んでいないことを意味します。書き込み変更があるかどうかに注意してください。
ソケット内で除外される要素。
を渡します。すべてを「リッスン」しています
秒とマイクロ秒を合わせてタイムアウト パラメータを形成します。
を渡すとブロック、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 '请求ip: ' . $ip . '端口: ' . $port . PHP_EOL; } else { // 否则说明是之前连接的客户端发来消息 $msg = socket_read($sock, 10240); socket_write($sock, strtoupper($msg)); echo $msg; } } }
$tmp_sockets ソケット リソースが新しい場合、クライアントが接続または切断するか、新しいメッセージを受信すると、
$tmp_sockets 配列を現在アクティブなソケット リソースに変更します。次に、配列を走査してビジネス ロジックを処理します
ソケットを使用して単純な 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 == '') return; $output = '<h1>this is php worker</h1>'; $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 をブラウザに表示すると、次の内容が表示されます:
同時に、サーバーは次の内容を出力します:
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+SocketシリーズのIO多重化とWebサーバーの実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。