サーバーを作ろう (毎週のハンズオン勉強会の資料)

ひとし あまの
ひとし あまの技術補佐員 at オーマ株式会社
サーバーを作ろう,[object Object],PHP でやるお(^ω^),[object Object]
目次,[object Object],勉強しよう,[object Object],TCP/IP,[object Object],Socket API,[object Object],クライアントとサーバー,[object Object],設計しよう,[object Object],サーバーの多重化,[object Object],ウェブプログラマが何故サーバーを作るの?,[object Object]
TCP/IP,[object Object],ストリーム型の通信プロトコル,[object Object],送ったら、送った順に届く,[object Object],順序を持った可変長バイト列(文字列に変換しやすい!)として送ったり、受け取ったりできるのでプログラミングしやすい,[object Object],ちゃんと届けられる,[object Object],相手が通信可能な状態かどうか分かる,[object Object],「相手が通信可能な状態じゃなかったら」という処理を書ける,[object Object],届いたかどうか分かる,[object Object],「届かなかったら」という処理を書ける,[object Object]
TCP/IP,[object Object],送ったら送った順に届く,[object Object],$fp = stream_socket_client('tcp://www.nicovideo.jp:80');,[object Object],fwrite($fp, "GET / HTTP/1.0");,[object Object],fwrite($fp, "Host: www.nicovideo.jp");,[object Object],echo stream_get_contents($fp);,[object Object],fclose($fp);,[object Object]
送ったら送った順に届く,[object Object],HTML がそのまま読めるよ,[object Object],www.nicovideo.jp,[object Object],送ったら,[object Object],送った順に届く,[object Object],PHP,[object Object],Web Server,[object Object],HTTP/1.1 200 OK,[object Object],<html>…</html>,[object Object],HTTP/1.1 200 OK,[object Object],<html>…</html>,[object Object],TCP/IP,[object Object],TCP/IP,[object Object]
TCP/IP,[object Object],ちゃんと届けられる,[object Object],$fp = stream_socket_client('tcp://www.nicovideo.jp:80', $errno, $errstr);,[object Object],if ($fp=== false) {,[object Object], throw new Exception($errstr);,[object Object],},[object Object],if (fwrite($fp, "GET / HTTP/1.0") === false) {,[object Object],  throw new Exception($php_errormsg);,[object Object],},[object Object],if (fwrite($fp, "Host: www.nicovideo.jp") === false) {,[object Object], throw new Exception($php_errormsg);,[object Object],},[object Object],echo stream_get_contents($fp);,[object Object],fclose($fp);,[object Object]
ちゃんと届けられる,[object Object],ちゃんと届いてるみたいだな,[object Object],www.nicovideo.jp,[object Object],PHP,[object Object],Web Server,[object Object],GET / HTTP/1.0,[object Object],Host: www.nicovideo.jp,[object Object],GET / HTTP/1.0,[object Object],Host: www.nicovideo.jp,[object Object],TCP/IP,[object Object],TCP/IP,[object Object],届いた,[object Object],届いた,[object Object]
TCP/IP,[object Object],考えてみよう,[object Object],ストリーム型じゃない通信プロトコルってどんなのだろう,[object Object],TCP/IP 以外のストリーム型通信プロトコルを考えてみよう,[object Object]
Socket API,[object Object],TCP/IP などで通信相手と接続するためのライブラリが socket,[object Object],接続後は、ファイルに対する読み書きの関数がそのまま使える,[object Object]
ファイル操作の関数が使える,[object Object],ソケットから読む,[object Object],ファイルから読む,[object Object],$fp = stream_socket_client(,[object Object],             'tcp://www.nicovideo.jp:80');,[object Object],fwrite($fp, "GET / HTTP/1.0");,[object Object],fwrite($fp, "Host: www.nicovideo.jp");,[object Object],while (fgets($fp) !== "") { },[object Object],$content = stream_get_contents($fp);,[object Object],if (!mb_check_encoding($content, 'UTF-8')) {,[object Object],  throw new Exception('Invalid encoding!');,[object Object],},[object Object],fclose($fp);,[object Object],libxml_use_internal_errors(true);,[object Object],$doc = new DOMDocument();,[object Object],$doc->loadHTML($content);,[object Object],libxml_clear_errors();,[object Object],echo $doc->getElementsByTagName('title'),[object Object],      ->item(0)->textContent;,[object Object],$fp = fopen('test.html', 'r');,[object Object],$content = stream_get_contents($fp);,[object Object],if (!mb_check_encoding($content, 'UTF-8')) {,[object Object],  throw new Exception('Invalid encoding!');,[object Object],},[object Object],fclose($fp);,[object Object],libxml_use_internal_errors(true);,[object Object],$doc = new DOMDocument();,[object Object],$doc->loadHTML($content);,[object Object],libxml_clear_errors();,[object Object],echo $doc->getElementsByTagName('title'),[object Object],      ->item(0)->textContent;,[object Object],まったく同じコードを使える,[object Object]
Socket API,[object Object],考えてみよう,[object Object],なんで、通信なのにファイルで抽象化してるんだろう?,[object Object]
クライアントとサーバー,[object Object],接続する側をクライアントと言う,[object Object],接続を待つ側をサーバーと言う,[object Object],それぞれで、接続が確立するまでのコードが違う,[object Object]
作ってみよう,[object Object],Mecabで形態素解析して、結果を返すサーバーと、そのクライアントを作る,[object Object],Mecabのインストール,[object Object],sudoapt-get install mecab # mecabプログラム,[object Object],sudoapt-get install libmecab-dev # mecab.so を作るのに必要,[object Object],sudoapt-get install mecab-naist-jdic mecab-jumandic-utf8 # mecabの UTF-8 の辞書,[object Object],sudoapt-get install build-essentials # php拡張をコンパイルするためのツール群,[object Object],sudopear channel-discover pecl.opendogs.org,[object Object],sudopear remote-list -c opendogs,[object Object],sudopear install opendogs/mecab-beta,[object Object],# 以下のファイルに extension=mecab.so を追加,[object Object],sudovim /etc/php5/cli/php.ini,[object Object]
クライアント側のコード,[object Object],繋ぐだけ,[object Object],エラー処理とかは各自勉強してね,[object Object],$fp = stream_socket_client('tcp://127.0.0.1:1111');,[object Object],fwrite($fp, json_encode($argv[1]) . "");,[object Object],$list = json_decode(fgets($fp, 1024));,[object Object],var_dump($list);,[object Object],fclose($fp);,[object Object]
サーバー側のコード,[object Object],接続を待って、 接続を確立する,[object Object],エラー処理とかは各自勉強してね,[object Object],$server = stream_socket_server('tcp://127.0.0.1:1111');,[object Object],while (true) {,[object Object],  $fp = stream_socket_accept($server);,[object Object],  while (!feof($fp)) {,[object Object],    $str = fgets($fp, 1024);,[object Object],fwrite($fp, json_encode(mecab_split(json_decode($str))) . "");,[object Object],  },[object Object],fclose($fp);,[object Object],},[object Object],fclose($server);,[object Object]
サーバー側の処理の多重化,[object Object],前の例では、サーバー側のコードは、常に一つのクライアントに対しての処理しかしない,[object Object],複数のクライアントに対して処理をしたい場合は、以下のいずれかの方法でサーバーの処理を多重化する必要がある,[object Object],フォークによる多重化,[object Object],イベントループによる多重化,[object Object],スレッドによる多重化,[object Object]
フォークによる多重化,[object Object],プロセスを分身させる。,[object Object],メモリは COW で節約されるけど、スレッドと比べてメモリを食う,[object Object],処理ごとに値が独立してるので、プログラミングが楽,[object Object],$server = stream_socket_server('tcp://127.0.0.1:1111');,[object Object],while (true) {,[object Object],  $fp = stream_socket_accept($server);,[object Object],  if (!pcntl_fork()) {,[object Object],    while (!feof($fp)) {,[object Object],      $str = fgets($fp, 1024);,[object Object],fwrite($fp, json_encode(mecab_split(json_decode($str))) . "");,[object Object],    },[object Object],fclose($fp);,[object Object],    exit;,[object Object], },[object Object],},[object Object],fclose($server);,[object Object]
スレッドによる多重化,[object Object],PHP では出来ない??,[object Object],フォークするより、省メモリ。,[object Object],とはいえ、スタック領域などのメモリは食う。,[object Object],マルチスレッドプログラミング難しい><,[object Object]
イベントループによる多重化,[object Object],フォークや、スレッドと比べて軽量,[object Object],$server = stream_socket_server('tcp://127.0.0.1:1111');,[object Object],stream_set_blocking($server, 0);,[object Object],$base = event_base_new();,[object Object],$event = event_new();,[object Object],event_set($event, $server, EV_READ | EV_PERSIST, 'ev_accept', $base);,[object Object],event_base_set($event, $base);,[object Object],event_add($event);,[object Object],event_base_loop($base);,[object Object],$id = 0;,[object Object],$fps = array();,[object Object],$bufs = array();,[object Object]
イベントループによる多重化,[object Object],function ev_accept($server, $flag, $base) {,[object Object],  global $id;,[object Object],  global $fps;,[object Object],  global $bufs;,[object Object],  $fp = stream_socket_accept($server);,[object Object],stream_set_blocking($fp, 0);,[object Object],  $id++;,[object Object],  $buf = event_buffer_new($fp, 'ev_read', NULL, 'ev_error', $id);,[object Object],event_buffer_base_set($buf, $base);,[object Object],event_buffer_timeout_set($buf, 30, 30);,[object Object],event_buffer_watermark_set($buf, EV_READ, 0, 0xffffff);,[object Object],event_buffer_priority_set($buf, 10);,[object Object],event_buffer_enable($buf, EV_READ | EV_PERSIST);,[object Object],  $fps[$id] = $fp;,[object Object],  $bufs[$id] = $buf;,[object Object],},[object Object]
イベントループによる多重化,[object Object],function ev_error($buf, $error, $id) {,[object Object],  global $id;,[object Object],  global $fps;,[object Object],  global $bufs;,[object Object],event_buffer_disable($bufs[$id], EV_READ | EV_WRITE);,[object Object],event_buffer_free($bufs[$id]);,[object Object],fclose($fps[$id]);,[object Object],  unset($fps[$id], $bufs[$id]);,[object Object],},[object Object],function ev_read($buf, $id) {,[object Object],  global $id;,[object Object],  global $fps;,[object Object],  global $bufs;,[object Object],  while ($str = event_buffer_read($buf, 1024)) {,[object Object],    $fp = $fps[$id];,[object Object],fwrite($fp, json_encode(mecab_split(json_decode($str))) . "");,[object Object],  },[object Object],},[object Object]
ウェブプログラマが何故サーバーを作るの?,[object Object],プロセスやマシンに縛られるのはやめよう,[object Object],1プロセスに拘らなくなる,[object Object],プログラミング言語に拘らなくてよくなる,[object Object],使いたいライブラリがあったら、なんでも使える。ソケットでプロセスを繋げばいい,[object Object],1マシンに拘らなくなる,[object Object],OS に拘らなくてもよくなる,[object Object],負荷分散も自由自在,[object Object]
1 of 22

Recommended

Thrift by
ThriftThrift
Thriftguestf259ae
1.4K views18 slides
Php s2 by
Php s2Php s2
Php s2Jun Chiba
542 views5 slides
Bossan dentoo by
Bossan dentooBossan dentoo
Bossan dentookubo39
1.2K views24 slides
Ruby&Active Support for expert 3 by
Ruby&Active Support for expert 3Ruby&Active Support for expert 3
Ruby&Active Support for expert 3xibbar
795 views15 slides
Title sample by
Title sampleTitle sample
Title samplepocketstudio33
44 views3 slides
20120423 hbase勉強会 by
20120423 hbase勉強会20120423 hbase勉強会
20120423 hbase勉強会Toshiaki Toyama
2.8K views53 slides

More Related Content

What's hot

Varnish by
VarnishVarnish
VarnishAyako Hatori
574 views14 slides
ゆるかわPhp by
ゆるかわPhpゆるかわPhp
ゆるかわPhpRyota Mochizuki
1.1K views83 slides
2020 acl learning_to_recover_from_multi-modality_errors_for_non-autoregressiv... by
2020 acl learning_to_recover_from_multi-modality_errors_for_non-autoregressiv...2020 acl learning_to_recover_from_multi-modality_errors_for_non-autoregressiv...
2020 acl learning_to_recover_from_multi-modality_errors_for_non-autoregressiv...広樹 本間
155 views36 slides
Perl and Email #3 ``Haineko''/Kyoto.pm #5 by
Perl and Email #3 ``Haineko''/Kyoto.pm #5Perl and Email #3 ``Haineko''/Kyoto.pm #5
Perl and Email #3 ``Haineko''/Kyoto.pm #5azumakuniyuki 🐈
1.4K views24 slides
Message delivery over XMPP network by
Message delivery over XMPP networkMessage delivery over XMPP network
Message delivery over XMPP networkHideki Saito
587 views25 slides
サーバー実装いろいろ by
サーバー実装いろいろサーバー実装いろいろ
サーバー実装いろいろkjwtnb
1.9K views11 slides

What's hot(20)

2020 acl learning_to_recover_from_multi-modality_errors_for_non-autoregressiv... by 広樹 本間
2020 acl learning_to_recover_from_multi-modality_errors_for_non-autoregressiv...2020 acl learning_to_recover_from_multi-modality_errors_for_non-autoregressiv...
2020 acl learning_to_recover_from_multi-modality_errors_for_non-autoregressiv...
広樹 本間155 views
Perl and Email #3 ``Haineko''/Kyoto.pm #5 by azumakuniyuki 🐈
Perl and Email #3 ``Haineko''/Kyoto.pm #5Perl and Email #3 ``Haineko''/Kyoto.pm #5
Perl and Email #3 ``Haineko''/Kyoto.pm #5
azumakuniyuki 🐈1.4K views
Message delivery over XMPP network by Hideki Saito
Message delivery over XMPP networkMessage delivery over XMPP network
Message delivery over XMPP network
Hideki Saito587 views
サーバー実装いろいろ by kjwtnb
サーバー実装いろいろサーバー実装いろいろ
サーバー実装いろいろ
kjwtnb1.9K views
JVM-Reading-ConcurrentMarkSweep by Minoru Nakamura
JVM-Reading-ConcurrentMarkSweepJVM-Reading-ConcurrentMarkSweep
JVM-Reading-ConcurrentMarkSweep
Minoru Nakamura2.4K views
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2 by azumakuniyuki 🐈
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
azumakuniyuki 🐈1.9K views
SPDY/3 の HTTP 重畳効果を測定する by 彰 村地
SPDY/3 の HTTP 重畳効果を測定するSPDY/3 の HTTP 重畳効果を測定する
SPDY/3 の HTTP 重畳効果を測定する
彰 村地5.2K views
H2O - making HTTP better by Kazuho Oku
H2O - making HTTP betterH2O - making HTTP better
H2O - making HTTP better
Kazuho Oku54.5K views
Chef の気まぐれ環境構築 〜季節の Capistrano を添えて〜 #jawsug by Takeshi Komiya
Chef の気まぐれ環境構築 〜季節の Capistrano を添えて〜 #jawsugChef の気まぐれ環境構築 〜季節の Capistrano を添えて〜 #jawsug
Chef の気まぐれ環境構築 〜季節の Capistrano を添えて〜 #jawsug
Takeshi Komiya11.8K views
Perl and Email #2/Kansai.pm第14回ミーティング@京都 by azumakuniyuki 🐈
Perl and Email #2/Kansai.pm第14回ミーティング@京都Perl and Email #2/Kansai.pm第14回ミーティング@京都
Perl and Email #2/Kansai.pm第14回ミーティング@京都
PowerShell 紹介 by tsudaa
PowerShell 紹介PowerShell 紹介
PowerShell 紹介
tsudaa2.2K views
Measurement of Maximum new NAT-sessions per second / How to send packets by @ otsuka752
Measurement of Maximum new NAT-sessionsper second / How to send packetsMeasurement of Maximum new NAT-sessionsper second / How to send packets
Measurement of Maximum new NAT-sessions per second / How to send packets
@ otsuka75218.8K views

Similar to サーバーを作ろう (毎週のハンズオン勉強会の資料)

about Thrift by
about Thriftabout Thrift
about ThriftNaoya Ito
2.3K views18 slides
Abコマンドを使ったウェブアプリケーションのパフォーマンス計測 by
Abコマンドを使ったウェブアプリケーションのパフォーマンス計測Abコマンドを使ったウェブアプリケーションのパフォーマンス計測
Abコマンドを使ったウェブアプリケーションのパフォーマンス計測Hidenori Goto
2.5K views11 slides
これからのアプリ開発はIPv6対応で行こう!(2014/09/20 OSC Hiroshima版) by
これからのアプリ開発はIPv6対応で行こう!(2014/09/20 OSC Hiroshima版)これからのアプリ開発はIPv6対応で行こう!(2014/09/20 OSC Hiroshima版)
これからのアプリ開発はIPv6対応で行こう!(2014/09/20 OSC Hiroshima版)v6app
3K views47 slides
勉強会資料① by
勉強会資料①勉強会資料①
勉強会資料①真亮 坂口
1.3K views20 slides
Dockerを使ったローカルでの開発から本番環境へのデプロイまで by
Dockerを使ったローカルでの開発から本番環境へのデプロイまでDockerを使ったローカルでの開発から本番環境へのデプロイまで
Dockerを使ったローカルでの開発から本番環境へのデプロイまでRyo Nakamaru
30.7K views119 slides
泥臭い運用から、プログラマブルインフラ構築(に行きたい) by
泥臭い運用から、プログラマブルインフラ構築(に行きたい) 泥臭い運用から、プログラマブルインフラ構築(に行きたい)
泥臭い運用から、プログラマブルインフラ構築(に行きたい) Akihiro Kuwano
4K views47 slides

Similar to サーバーを作ろう (毎週のハンズオン勉強会の資料)(20)

about Thrift by Naoya Ito
about Thriftabout Thrift
about Thrift
Naoya Ito2.3K views
Abコマンドを使ったウェブアプリケーションのパフォーマンス計測 by Hidenori Goto
Abコマンドを使ったウェブアプリケーションのパフォーマンス計測Abコマンドを使ったウェブアプリケーションのパフォーマンス計測
Abコマンドを使ったウェブアプリケーションのパフォーマンス計測
Hidenori Goto2.5K views
これからのアプリ開発はIPv6対応で行こう!(2014/09/20 OSC Hiroshima版) by v6app
これからのアプリ開発はIPv6対応で行こう!(2014/09/20 OSC Hiroshima版)これからのアプリ開発はIPv6対応で行こう!(2014/09/20 OSC Hiroshima版)
これからのアプリ開発はIPv6対応で行こう!(2014/09/20 OSC Hiroshima版)
v6app3K views
Dockerを使ったローカルでの開発から本番環境へのデプロイまで by Ryo Nakamaru
Dockerを使ったローカルでの開発から本番環境へのデプロイまでDockerを使ったローカルでの開発から本番環境へのデプロイまで
Dockerを使ったローカルでの開発から本番環境へのデプロイまで
Ryo Nakamaru30.7K views
泥臭い運用から、プログラマブルインフラ構築(に行きたい) by Akihiro Kuwano
泥臭い運用から、プログラマブルインフラ構築(に行きたい) 泥臭い運用から、プログラマブルインフラ構築(に行きたい)
泥臭い運用から、プログラマブルインフラ構築(に行きたい)
Akihiro Kuwano4K views
ゲームのインフラをAwsで実戦tips全て見せます by infinite_loop
ゲームのインフラをAwsで実戦tips全て見せますゲームのインフラをAwsで実戦tips全て見せます
ゲームのインフラをAwsで実戦tips全て見せます
infinite_loop6.1K views
Clrh 110716 wcfwf by Tomoyuki Obi
Clrh 110716 wcfwfClrh 110716 wcfwf
Clrh 110716 wcfwf
Tomoyuki Obi1.2K views
Railsの運用について by Yuuki Namikawa
Railsの運用についてRailsの運用について
Railsの運用について
Yuuki Namikawa1.6K views
Html5, Web Applications 2 by totty jp
Html5, Web Applications 2Html5, Web Applications 2
Html5, Web Applications 2
totty jp786 views
2012 osc北海道 セッション資料「blackjumbodog利用のすすめ」 by Shinichi Hirauchi
2012 osc北海道 セッション資料「blackjumbodog利用のすすめ」2012 osc北海道 セッション資料「blackjumbodog利用のすすめ」
2012 osc北海道 セッション資料「blackjumbodog利用のすすめ」
Shinichi Hirauchi7.2K views
Erlangご紹介 websocket編 by Masatoshi Itoh
Erlangご紹介 websocket編Erlangご紹介 websocket編
Erlangご紹介 websocket編
Masatoshi Itoh2.8K views
Couch DB in 15minutes by Yohei Sasaki
Couch DB in 15minutesCouch DB in 15minutes
Couch DB in 15minutes
Yohei Sasaki1.2K views
Qlik TechFest C-5 Qlikエンジンのサーバーサイド拡張(SSE)の 基礎から実装まで by QlikPresalesJapan
Qlik TechFest C-5  Qlikエンジンのサーバーサイド拡張(SSE)の 基礎から実装までQlik TechFest C-5  Qlikエンジンのサーバーサイド拡張(SSE)の 基礎から実装まで
Qlik TechFest C-5 Qlikエンジンのサーバーサイド拡張(SSE)の 基礎から実装まで
QlikPresalesJapan463 views
FD.io VPP事始め by tetsusat
FD.io VPP事始めFD.io VPP事始め
FD.io VPP事始め
tetsusat2.3K views
PHP、おまえだったのか。 いつもHTTPメッセージを 運んでくれたのは。 by sasezaki
PHP、おまえだったのか。 いつもHTTPメッセージを 運んでくれたのは。PHP、おまえだったのか。 いつもHTTPメッセージを 運んでくれたのは。
PHP、おまえだったのか。 いつもHTTPメッセージを 運んでくれたのは。
sasezaki7.6K views

サーバーを作ろう (毎週のハンズオン勉強会の資料)

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.