$descripto 「 spec = array( array("pipe", "w"). / / stdout a 「「 ay("file". "/tmp/e 「「 or-output. txt" $pipes = a 「「 ay(); / / サブプロセスを立ち上ける $child = p 「 oc_open( ・ php ・ . $path. $descripto 「 spec. $pipes); 2 6 fclose($conn); fwrite($conn, "HTTP/I.1 404 N0tFound\r\n"); }else { fwrite($conn. $content); fwrite($conn, "\r\n"); fw 「 ite($conn, "Content-Type: text/html\ 「 \n"); 〃 HTML 固定にするよ fw 「 ite($conn. "Content-Length: ・ . strlen($content) . fw 「 ite($conn, "HTTP/I . 1 200 OK\ 「 \n"); if ($content) { $content = file_get_contents($path); } else { putenvCQUERY_STRlNG='); p 「 oc—close($child); fclose($pipes[l]); $content = st 「 eam_get_contents($pipes[l]); 〃レスポンスを受け取る fclose($pipes[0]); fw 「 ite($pipes[0], $ 「 equest → body); 〃リクエストボディを書き込む
>path); fclose($conn); fwrite($conn. "HTTP/I.1 404 N0tFound\r\n"); } else { fw 「 ite($conn, $content); fwrite($conn, "\r\n"); fw 「 ite($conn, "Content-Type: text/html\r\n"); と、 png を返せるようになる 〃 HTML 固定にするよ。拡張子とかで判別して img/png とかにする fwrite($conn. "Content-Length:" . strlen($content) . "\ 「 \n"); fwrite($conn. "HTTP/I.1 200 OK\ 「 \n"); if ($content) { $content = file_get_contents($path); if ($ 「 equest → method = = ・ GET' & & is—file($path)) { 〃 GET で来ていて、ファイルが有ったら読む 2 0 ン explode( ・・ , $ 「 equestCommand); list ($ 「 equest → meth0d. $ 「 equest → path. $ 「 equest → ve 「 sion) = 〃スペース区切りでメソッド [GETIPOSTIDELETEIPUT] 、パス、パージョ $requestCommand = t 「 im(fgets($conn)); / / 1 行だけ読む、 1 行目はリクエスト内容そのもの $request = new\stdClass(); function buildRequest($conn) { fclose($socket);
( H ム P す第 . イ じゃあ、 HTTP サーバーを作ってみるにや fo 「 ()i = 0 ; $i く 1000 : $ i + + ) { $content = while ($conn = st 「 eam socket accept($socket)) { } else { echo "$er 「 st 「 ( $ e 「「 no ) く b 「 / > \ n " if (!$socket) { $e 「 rstr); $socket = stream—socket—se 「 ver("tcp://O. 0.0.0:8080" く ?php php 鉄ニャンはそう言うと、ⅵに凄い勢いでコードを打ち込み始めた。 「じゃあ、 HTTP サーバーを作ってみるにや」 fclose($socket); fclose($conn); fw 「 ite($conn. $content); fwrite($conn. "Content-Type: text/html\r\n"); 〃 HTML 固定にするよ fw 「 ite($conn, "Content-Length: ・ . st 「 len($content) . "\ 「 \n"); fwrite($conn. "HTTP/I.1 200 OK\r\n"); 〃さっきの cu 「 [ で返ってきたレスポンスへッダそっくりなのに注目 $content . "<P style= ・ C0[0 「 : 「 ed; font-weight:bold; ・ > にやーんく /
Date: Sat. 15 Oct 2016 07 : 42 : 20 GMT Serve 「 : Apache/2.2.31 Last-Modified: Sun, 27 Dec 2015 12 : 09 : 53 GMT ETag: " 1520031-5774-527e010e2a640 " Accept-Ranges: bytes Content-Length: 22388 Content-Type: text/html く !DOCTYPE html> <html> <head> <title> でさはたん公式 Web ページ lTOP</titIe> charset=utf-8"> く link rel="stylesheet" h 「 ef="css/base. css" media="sc 「 een"> く [ i n k 「 e [ = " s t y [ e s h e e t " h 「 e f = " c s s / c 0 m m 0 n . c s s ? h 0 g e media=••sc 「 een ・ > く meta name="desc 「 iption" content=" 新ジャン丿レ ! ? かわいいイラストと ちょっぴりダークなショートストーリーと、わかりやすい PH P ソースコー ドでデザインパターンをもっと身近に感じる擬人化本 ! C85 にてお昼には完 売してしまった宿版 ( 11 パターン収録 ) から内容を再編し 23 パターン全て を収録した完全版として帰ってきました ! ! ゲストライターにあさば氏をお迎 えし、 SS 部分もクオリティアップ。 ( 今回は明るい話もあります ! あります ! ! ) 総ページ数 96 ページ ! 読みこたえたっぷりの一冊です。 " > <meta name="keywo 「 ds" content=" デザインパターン . でざはたん , PHP"> <meta http-equiv="Content-Type" content="text/html; く meta property="og:site—name" content=" でざはたん公式 Web ページ く meta p 「 operty="og:u 「じ content="http://www.dezapatan.com/> ( 中略 )
fclose($socket); function buildRequest($conn) { $request = new\stdClass(); $requestCommand = t 「 im(fgets($conn)); list ($request → method, $ 「 equest → path. $ 「 equest → ve 「 sion) = explode(). $ 「 equestCommand); while (($char = fgetc($conn)) ! = = false) { $line . = $cha 「 ; fo 「 each (explode("\n". $line) as $heade 「 ) { $label = strtouppe 「 (strt 「 ($tmp[l]. ・ $ 「 equest → $label = t 「 im($tmp[2]); if (isset($ 「 equest → CONTENT_LENGTH)) { $ 「 equest → body = f 「 ead($conn, intval($ 「 equst- >CONTENT_LENGTH)); b 「 eak; 「 etu 「 n $ 「 equest; 「これ、パイプの部分が良く分からないけど、なんとなく拡張子が " php " なら プログラムを起動するっていうところが、主な変更点だよね ? 」 「その通りだにや。パイプについては、 Linux の仕組の基本だから、そのうち こでは「プログラムとプログラムの間を通信する仕組」 説明するにや。一旦、 2 7
″ここからは区切り文字くるまでひたすら読む while (($char = fgetc($conn)) ! = = false) { $line . = $char; ″ \r\n\ 「 \n までがヘッダ foreach (explode("\n". $line) as $heade 「 ) { 〃ラベルと内容で分ける $label = strtouppe 「 ()t 「 t 「 ($tmp[l], ・ $request → $label = t 「 im($tmp[2]); 〃リクエストボディがあるようなら、ボディを読む if (isset($ 「 equest → CONTENT—LENGTH)) { $ 「 equest → b0dy = fread($conn, intval($ 「 equst- >CONTENT_LENGTH)); b 「 eak; 「 etu 「 n $ 「 equest; 「それじゃ、これを simple. php として保存して、 php simple. php として起動する。 プラウザで " http : 〃 192.168.33.10 : 8080 / simple. php " にアクセスしてみるにや」 「お、今書いたソースコードが降ってきた」 「 simple. php を保存したディレクトリに適当に HTML ファイル作って遊んでみ たり、メソッドが POST の場合を作ってみて curl で post を送ってみたりして、 $request->body の中身を見てみると良いにや」 「ふう・・ ・・なるほど、 buildRequest 関数の中がちょっと難しいけど、ググりな
がら読めば分からないって程じゃないな。そこを一旦読み飛ばして見てみれば、 $content を IOOO 個にやーんするか、ファイルを読みこんで作っているかの 違いだけか。って、もう 2 時じゃねーか。ェロゲもできなかったけど、もう寝 るぞッ ! ! 」 そう言って、僕は鉄ニャンが寝るための布団を用意しながら、 こし、つ・・・・・う意 外と凄いャツなのでは ? と思い始めていた。 2 2
0N7 凹 D 5 # CGI 「そういえば、 Web サーバー作っている時に拡張子が php だったら PHP を起動するのを作る時に、 CGI がどうのって言っていたけど、ど ういう意味なの ? 」 「 CGI は Common Gateway lnterface の略にや。あそこではややこしい ことしたくなかったから拡張子 php の時に、 PHP を決め打ちで起動し ていたけど、本来は CGI という Web サーバーから外部のプログラムに データを渡しながら起動するための規格があるにや。って言っても環境 変数と標準入力を使ってデータを渡して、標準出力をそのままクライア ントへ返してやることが決まってるだけにや。たとえばにや」 # !/bin/sh echo "HTTP/I.1 200 OK\r\n" ech0 "Content-Length:2\r\n" echo "Content-Type: text/html\ 「 \n" echo "\r\n" echo "OK" 「こういうシェルスクリプトを " index. cgi " という名前で置いて、パー ションを chmod で 755 にしておくにや。」 「ふむふむ」 「そうしたら試しに . /index. cgi とシェルに打つにや。」 「うん、想像通りリクエストヘッダとリクエストボディが出たね。 この このプログラムで実行してね " って意味 1 行目の # ! から始まるのが、 だったよね ? 」 「そうにや、具体的にはソースコードの 1 7 行目の拡張子で制限してい るところを直して、 25 行目の php を直接起動しているところを $path で動くようにすれば良いにや。これでサーバーにアクセスすると OK っ て出るにや。まあ、要するに本当は言語とかどうでも良くて、シェルで 実行出来るものなら、シェルで実行した結果をそのままクライアントへ 返せるということにや。詳しいことは RFC3875 を読むにや」 ツ 3 3
でリクエストを送ってみるにや」 cu 「 l-i http://www.dezapatan.com/img/thumb/17.png 「うわ、なんか読めないの出てきた ! ! 」 「これは画像ファイルの中身が落ちてきているにや。プラウザは、 して表示しているんだにや。じゃあ、整理してみるにや」 これを解釈 3 プラウザが HTML を 解釈して画面に表示 する content く html> く head> く /html> WEB プラウザ プラウザから URL を元に Web サーバーヘリクエスト を送る ( リクエスト ) GET/index . php -type:text/html 2 Web サーバーがリクエストの 内容を元に HTML を生成してプ ラウサへ返す ( レスポンス ) 0 WEB 単純な仕組みにや。 HTML のパー ス中に画像や C S S の U R L があっ たう、これだけ再帰的に繰り返 すにや。要す 5 にカ技だにや。
「で、これを simple. php として保存して、それじゃ、これを "php simple. php" で起動してプラウザで " http : 〃 192.168.33.10 : 8080 / " にアクセスしてみるにや。 もし、ちゃんと動かないようなら、 " php-lsimp . php " とするとタイプミス とかは教えてくれるにや」 「おお、プラウザに " にやーん " って出た。ん、これ、世界中がアクセスでき る場所に置いたら、世界中に " にやーん " を返せるってことか ? 」 「そうにや」 「 fwrite って、アレだよね ? print みたいなもので、ファイルに書き込むんだっ け ? でも、こで返す先って通信相手のプラウザじゃないのか ? 」 「そうにや。 UN Ⅸの世界ではなんでもファイルとして見做そうとしている にや。つまり、ソケット ( 通信 ) もファイルにや」 「ふーん、分かるような分からないような。あれ ? このプログラム、リクエス トヘッダとして送ってきてるはずの、 GET とか POST とか一切出てこないぞ ? その辺は読まないのか ? 」 「良いところ気付いたにや。それじゃ、 GET の時だけファイルを返せるように $ 「 equest = buildRequest($conn); 〃リクエストの内容を解析する $buffe 「 s = while ($conn = stream_socket accept($socket)) { 〃リクエスト来るまで待ち } else { echo "$errstr ( $ e 「「 no ) く b 「 / > \ n " if (!$socket) { $socket = stream_socket_se 「 ve 「 ("tcp://0.0.0.0:8080" 〃サーパー待ち受けでソケットオープン く ?php php してみるかにや ? 」 $content= null; $path = 引 R $ 「 equest-