490 likes | 597 Views
システムプログラミング演習. 田浦. 演習を通して学んでほしいこと. ネットワークプログラミング インターネットの基本 ソケット HTTP (web のプロトコル ) HTML ( ほんの少し ) スレッドプログラミング Web サーバの基本的な構成 ( ミニチュア ). 情報源. UNIX : man ページ man recv man 2 recv man 3 recv Windows : MSDN ライブラリ Online 図書から CD を借りてインストール. インターネットの復習. IP アドレス 133.11.23.10 etc.
E N D
演習を通して学んでほしいこと • ネットワークプログラミング • インターネットの基本 • ソケット • HTTP (webのプロトコル) • HTML (ほんの少し) • スレッドプログラミング • Webサーバの基本的な構成(ミニチュア)
情報源 • UNIX : manページ • man recv • man 2 recv • man 3 recv • Windows : MSDNライブラリ • Online • 図書からCDを借りてインストール
インターネットの復習 • IPアドレス • 133.11.23.10 etc. • IP (Internet Protocol) • IPアドレスを指定すると(世界中どこへでも)パケットをがんばって届けてくれる(厳密にはウソ.後ほど) • 失敗あり • TCP (transfer control protocol) • IPの上の“reliable”なレイヤ • ポート番号による複数の入り口・出口管理 • 数え切れないアプリがこれを利用している
IPアドレスを調べてみよう • Win: ipconfig • Unix: /sbin/ifconfig –a • 接続時に自動的に重複なく割り当てられていることがほとんど(DHCP)
さっきのはウソ • 一部のアドレスは「ローカルアドレス」 • 10.0.0.0 – 10.255.255.255 • 172.16.0.0 – 172.31.255.255 • 192.168.0.0 – 192.168.255.255 • LANの外からはつなげない • でもLANの定義は微妙…
ソケット • プロセス間通信(含むインターネット通信)のためのAPI • 本演習ではソケットをTCPを用いたインターネット通信のために使う
基本概念 • クライアント(=電話をかける人)s = socket(…);connect(つなぎたいIPアドレスとポート); /* 電話かける */send/recv(s, …); • サーバ(=電話を受ける人)s = socket(…);sにIPアドレスとポートを割り当て(電話番号登録);new_s = accept(s); /* 待ち受け */send/recv(new_s, …);
ソケット練習課題 • 送られてきた文字列を表示するだけのサーバ • ブラウザがどんな文字列を送ってきているのかを調べるのに役に立つ
HTTP/HTML • ブラウザとWebサーバのやり取り(のほんの一部) • HTTP (Hypter Text Transfer Protocol) • HTML (Hyper Text Markup Language) • テキスト・参考書を読むのもよいが, • ブラウザは既にHTTPのリクエストをしゃべる • サーバは既にHTTPのリプライをしゃべる • 先の課題でブラウザのメッセージを表示できる • telnetコマンドでサーバの返事を表示できる
connect GET <パス> HTTP/1.0 …<空行> send recv send HTTP/1.1 200 OK… <空行> <ページの内容> recv 先週の復習 サーバ クライアント socket socket bind & listen accept
/ remember78478931 /new_n/ セッション(ゲーム)ID new game 6 digits8 digits… /xxx_S/ next 1 2 … END /xxx_?/ (不正解) /xxx_X/ (正解) wrong! congrat! /xxx_n/ (正解) 入力パス名と状態遷移
/ new game 6 digits8 digits… 複数ゲームの同時進行が可能な構成 /new_n/ /new_n/ /new_n/ /new_n/
スレッドの概念 • スレッド: プログラムの文面を順に実行する「主体」 • main() { … } で … が実行されるのは,OSがmainを実行するスレッドを生成して実行しているから • プログラム中でスレッドを生成するAPIが存在する
スレッドAPI • UNIX: POSIXスレッド(Pthreads) • Windows: Win32スレッド • 概念はほとんど同じ(見た目はソケットほど似てはいないが…) • 生成 • 同期(タイミングの制御) • 以下,Pthreadsに準じて説明
生成 • pthread_create(…, f, x, …); • f (x)を実行する「スレッドを生成」 • つまり,pthread_create(…, f, x, …);<…>で,f (x)と<…>が並行に実行される • f (x)と<…>はメモリを共有する
“並行に”実行されるとは? • たくさんCPUがあれば本当に「同時に」実行される • 一般には,「あるだけのCPU」を「存在するだけのスレッド」がかわりばんこに使う(OSの制御) • プログラムは「かわりばんこ」を意識しなくてよい
プログラムの書かれ方 実際 CPU
スレッド利用上の大注意 • 次の結果は? initially:x = 1; スレッド2:g (){ x = x * 5;} スレッド1:f (){ x = x * 10;}
同期の概念 • スレッドの「実行タイミング」の制御 • 排他制御: 「これ」と「あれ」を同時に実行してはいけない(どちらが先でも良い) • 生産者消費者同期: 「これ」がおわってから「あれ」を実行すべし • 両者とも頻繁に用いられ,本課題でも使う
排他制御 pthread_mutex_t m;pthread_mutex_init(&m); スレッドA:… pthread_mutex_lock(&m); pthread_mutex_unlock(&m); … スレッドB: … pthread_mutex_lock(&m); pthread_mutex_unlock(&m); …
生産者消費者同期 • 疲れるのでまた来週(テキストを読んでおいてください)
本課題でのスレッドの利用 • 全てのリクエスト(acceptからのreturn)に「そのリクエスト処理」スレッドを生成 • / : これまでどおり • /new_yyy/ : (新しいセッション)だったら,そのスレッドは,「そのセッション専門スレッド」になり,以降そのセッションへのメッセージを待つ • /xxx_yyy/ : セッションID xxxに対応するスレッドに yyyを渡す
mainスレッド accept /xxx_yyy/ セッションスレッドxxxにメッセージyyyをとどける / これまで通り /new_?/ セッションスレッド wait_for_msg 正しい受け渡しの ための同期!
本日のメニュー • 生産者消費者同期 • おまけ: 本物のwebサーバとの違い
Windows Socketの初期化 WORD wVersionRequested = MAKEWORD( 2, 2 ); WSADATA wsaData[1]; if (0 != WSAStartup(wVersionRequested, wsaData)){ /* 失敗! ありえない! */}
生産者消費者同期とは • スレッドSの操作Aがおわるまで,スレッドTの操作Bを待たせたい • 典型的な状況 • A : データの生産者 • B : データの消費者 • but, 上に限らず頻出する状況 S T A result = 10; … = result; B
本課題の生産者消費者同期 メインスレッド G: セッション(1スレッド/ゲーム) • 注: 実は2つの同期の複合 • GはRが書く前に読んではいけない • RはGが(一つ前のデータを)読む前に(次のデータを)書いてはいけない • 「有限バッファ」問題 create R: リクエスト処理 1スレッド/リクエスト put_data get_data
条件変数(condition variable) • 一般的に,「ある条件が成立するまで待つ」を実現するprimitive • 例 (いくらでも…) • x + y > 0 になるまで待つ • Q (queueオブジェクト)が空でなくなるまで待つ • f (x, y, z)が成立するまで待つ • 要するに何にでも使える強力primitive
基本フォーム • C(x, y, z)が成立するまで待ちたい時: • pthread_mutex_lock(m);while (!C(x, y, z)) {mをunlockし,ブロックする; 起きたらまたmをlock;}x, y, zなどをいじる必要なら,他の待ってる人たちを起こすpthread_mutex_unlock(m);
条件変数API • pthread_cond_t c; pthread_mutex_t m; • pthread_cond_init(&c); • pthread_cond_wait(&c, &m); • mをunlockし,cの上でブロックする.起こされたらまたmをlockする • pthread_cond_broadcast(&c); • cでブロックしている人全員をたたき起こす
有限バッファ with 条件変数 • 容量1の有限バッファ • typedef struct { int data; int full; mutex_t m; cond_t c } bb;
有限バッファ with 条件変数 (2) • bb_get(bb * b) { lock(&b->m); while(!b->full) wait(&b->c); t = b->data; b->full = 0; broadcast(&b->c); return t;}
有限バッファ with 条件変数 (3) • bb_put(bb * b, int x) { lock(&b->m); while(b->full) wait(&b->c); b->data = x; b->full = 1; broadcast(&b->c);}
関連primitive: セマフォ • mutexの一般化(n人まで同時利用可能) • Windows (not in Pthreads) • HANDLE s = CreateSemaphore(…); • wait: • WaitForSingleObject(s, …); • WaitForMultipleObjects(…); • signal: • ReleaseSemaphore(s, …);
補足(1) セッションID • セッションIDの簡単な生成法=スレッドのスタック上の変数のアドレス • do_session() { char dummy; long session_id = (long)&dummy; …}
補足(2) 有限バッファメモリ管理 • typedef struct { … } session_table_entry; • session_table_entry session_table[MAX_SESSIONS]; • 操作: • 新しいsessionの登録 • 与えられたsession IDのentry検索 • いたるところに同期が必要 • 本課題ではむなしいが,10000 req/secのサーバを作っている気分で
おまけ(1) 巷のwebサーバとの違い • 本物のwebサーバは • 状態をメモリに残さない.データベースと連携.セッションIDをcookieとしてブラウザに送り返す • 基本サービス以外は外部プログラム(CGI)を起動する(拡張性) • スレッドプール(同時処理に上限) • スレッドの変わりにプロセスを使うこともある
おまけ(2): VMWare/Linuxオペレーション • Linux in VMWareをインターネットにつなげる • VMWareのネットワーク構成 • IP接続 • WWWブラウザ • メール • Linux in VMWare ホストWindowsとの通信 • ホスト -> ゲストの接続 • ファイルコピー • ファイル共有
VMWareのネットワーク構成 • 残念なこと 無線LANではBridgedでは使えない
診断手順 • /sbin/ifconfig –a • ping • TCP接続 • ブラウザ->webサーバ • telnet->何かのサーバ(web, メール, etc.) • 本演習で作ったプログラム!
ダメなとき • /sbin/ifconfig –aでIPアドレスが変(0.0.0.0とかゴミっぽい) • /sbin/ifdown –a • /sbin/ifup –a • 直らなければ? • NAT/Host-Onlyでやってみる • 複数の同時接続を許すISPか? 許さなければBridgedは無理
ダメなとき • pingが通らない • 近場(=ホストOS)に通す • ホストOS (Windows)のアドレスはipconfigでチェック • Bridged, NAT, Host-Onlyで見るべき値が違う • 近場に通らなければLinuxの問題か? • 近場に通るがインターネット(e.g., yahoo)に通らない • Host-Onlyじゃない? • ファイアウォールなど?
pingが通るけどWWWが動かない • あまりない…
pingが通るがメールが動かない • まずメールの設定をせよ • emacs + mew • 設定方法は後日HPにのせます
設定したがなぜか動かない • 色々な理由がある • SPAMとの戦い • メールの仕組みを多少知っておいたほうが良い
メールの仕組み メーラ (mew, outlook) 送信(認証なし) 受信 (認証あり) ポート25 SMTPサーバ POP/IMAPサーバ ポート110 (POP)
メールが送れないありがちな理由 • SMTPサーバ設定ミス • telnet <サーバ名> 25でつながるか? • 受け取りを拒否される • ありがち: SMTPサーバが,LAN外からの送信を拒否している • × 大学 -> ISPのメールサーバ • × ISP -> 大学のメールサーバ
メールが受け取れないありがちな理由 • POP/IMAPサーバ設定ミス • telnet <サーバ名> 110 (POP) • telnet <サーバ名> 143 (IMAP) • でつながるか • LAN外からの危ない認証法拒否 • ×大学 <- ISP POPサーバ • × ISP <- 大学 POPサーバ