330 likes | 450 Views
web プロキシ HTTP1.0 ヒント. CS-B3 ネットワークプログラミング &情報科学科実験 I. このスライドについて. このスライドでは皆さんがプログラムを書いたり,関数を調べたりする過程で行き詰ると予想される部分について簡単に解説します.. このスライドの目的は自主学習のサポートであり,説明が簡略化されています.完全な理解には自主学習が必要なので注意してください.. 目次. web プロキシとは 何を実装すればよいのか 実装方法の例 web サーバの特定方法 実装をする上での注意. web プロキシとは. 一般的な通信は直接通信.
E N D
webプロキシ HTTP1.0 ヒント CS-B3 ネットワークプログラミング &情報科学科実験I
このスライドについて このスライドでは皆さんがプログラムを書いたり,関数を調べたりする過程で行き詰ると予想される部分について簡単に解説します. このスライドの目的は自主学習のサポートであり,説明が簡略化されています.完全な理解には自主学習が必要なので注意してください.
目次 • webプロキシとは • 何を実装すればよいのか • 実装方法の例 • webサーバの特定方法 • 実装をする上での注意
webプロキシとは 一般的な通信は直接通信 webサーバ ブラウザ
webプロキシとは proxy = 「代理」 webサーバとのデータのやりとりを中継する webサーバ ブラウザ プロキシ $./proxy
何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ proxy側 listen() webサーバ listen() $./proxy
何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ proxy側 listen() webサーバ listen() $./proxy ブラウザ側の connect()
何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ webサーバ listen() $./proxy プロキシ側で accept()
何を実装すればよいのか プログラムの流れ webサーバ ブラウザからの リクエスト ブラウザ プロキシ webサーバ listen() $./proxy
何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ webサーバ listen() $./proxy リクエストから webサーバを特定
何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ webサーバ listen() $./proxy webサーバへの connect()
何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy webサーバが accept()
何を実装すればよいのか プログラムの流れ webサーバ ブラウザからの リクエストを 転送 ブラウザ プロキシ $./proxy
何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy webサーバからの レスポンス
何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy webサーバからの レスポンスを 転送
何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy ソケットクローズ
何を実装すればよいのか HTTP1.0では 1リクエスト +1レスポンス = 1コネクション 各リクエストごとに接続を確立します.
何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ $./proxy
何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ proxy側 listen() webサーバ listen() $./proxy ブラウザ側の connect()
何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ webサーバ listen() $./proxy プロキシ側で accept()
何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ listen用ソケットは残しておく webサーバ listen() $./proxy 別スレッド,または別プロセス proxy accept()したら 後は並列処理に任せる
何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ listen用ソケットは残しておく webサーバ listen() $./proxy 別スレッド,または別プロセス proxy
何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ webサーバ listen() $./proxy ブラウザ側の connect() 別スレッド,または別プロセス proxy
何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ webサーバ listen() $./proxy プロキシ側で accept() 別スレッド,または別プロセス proxy
何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ listen用ソケットは残しておく webサーバ listen() $./proxy 別スレッド,または別プロセス proxy proxy
実装方法の例 main{ listenSocket = listen中のソケットを作成; sockaddr_in変数の各種メンバの設定; bind(); listen(); while (1) { browserSocket = accept(listenSocket, …); /* ブラウザからlistenSocketへの接続要求をaccept(); */ スレッド(またはプロセス)の作成; /*子スレッドor子プロセスに送受信処理を実行させる*/ /*browserSocketをスレッド(またはプロセス)に渡す*/ }/*main関数はaccept→子スレッドorプロセスの作成を繰り返す*/ } ※あくまでも一例です.また,引数や実装方法が簡略化されています.
実装方法の例 スレッド(またはプロセス){ recv(browserSocketからの文字列 → buffer); webserverSocket = socket(); hostName = bufferからwebサーバのホスト名を抜き出す; hostAddress = hostNameからwebサーバのIPアドレスを求める; hostPort = webサーバならば通常は80を代入;(well-known port) sockaddr_in型変数のメンバへの設定; connect(); send(bufferの文字列 → webserverSocket) while(1) { browserSocketまたはwebserverSocketが読み取り可能になるまで待機; if (browserSocketからrecv()できるなら) { recv(browserSocketからの文字列 → buffer); /* ① */ if (recv()が失敗したら) break; send(bufferの文字列 → webserverSocket) /* リクエストの転送 */ if (①のrecv()の結果,browserSocketがクーロズされていたとわかった(つまり0バイト受信)) { break; } } if (webserverSocketからrecv()できるなら) { recv(webserverSocketからの文字列 → buffer); /* ② */ if (recv()が失敗したら) break; send(bufferの文字列 → browserSocket) /* レスポンスの転送 */ if (②のrecv()の結果,webserverSocketがクーロズされていたとわかった(つまり0バイト受信)) { break; } } } close(browserSocket); close(webserverSocket); return 0; } スレッドorプロセスによって作成した子の中で Selectを用いればよい ※あくまでも一例です.また,引数や実装方法が簡略化されています.
webサーバの特定方法 HTTPのリクエスト,レスポンスはテキストデータである. HTTP1.0 プロキシを用いたリクエスト GET http://www.inf.shizuoka.ac.jp/ HTTP/1.0\r\n Host: www.inf.shizuoka.ac.jp\r\n (以下省略)
webサーバの特定方法 HTTP1.0 プロキシを用いたリクエスト GET http://www.inf.shizuoka.ac.jp/ HTTP/1.0\r\n Host: www.inf.shizuoka.ac.jp\r\n (以下省略) ホスト名が特定できた =名前解決でIPアドレスが分かる ※接続先ポート番号は今回は80番で固定でOK
webサーバの特定方法 HTTP1.0 プロキシを用いたリクエスト GET http://www.inf.shizuoka.ac.jp/ HTTP/1.0\r\n Host: www.inf.shizuoka.ac.jp\r\n (以下省略) “Host: ”がないならば “GET”からホスト名を特定 ※接続先ポート番号は今回は80番で固定でOK
実装上の注意 webブラウザによっては… プロキシを使う場合と使わない場合ではリクエストが異なる! プロキシ使用 プロキシ未使用 GET http://www.inf.shizuoka.ac.jp/ HTTP/1.0\r\n Host: www.inf.shizuoka.ac.jp\r\n (以下省略) GET / HTTP/1.0\r\n Host: www.inf.shizuoka.ac.jp\r\n (以下省略)
実装上の注意 webブラウザによっては… プロキシを使う場合と使わない場合ではリクエストが異なる! プロキシ使用 プロキシ未使用 GET http://www.inf.shizuoka.ac.jp/ HTTP/1.0\r\n Host: www.inf.shizuoka.ac.jp\r\n (以下省略) GET / HTTP/1.0\r\n Host: www.inf.shizuoka.ac.jp\r\n (以下省略) リクエストをwebサーバに転送するときは“GET”メソッドから “http://ホスト名”を削除しておこう!! ※メソッドは”GET”だけとは限りません あくまでも“http://ホスト名”を削除するだけで それ以外の部分をプロキシ側で書き換えてはいけません
まとめ webプロキシプログラムは ブラウザからのconnect()をaccept()する ブラウザとの通信用のソケットを並列処理に持っていく 以下,並列処理 ブラウザからリクエストを受け取る ブラウザのリクエストからwebサーバを特定する webサーバとの通信用ソケットを作成し,connect()する ブラウザのリクエスト,webサーバからのレスポンスを転送する(このとき,リクエストはあらかじめ適切に変換しておく) ソケットを閉じる