webプロキシ HTTP1.0 ヒント CS-B3 ネットワークプログラミング &情報科学科実験I このスライドについて このスライドでは皆さんがプログラムを書いたり,関数を調べたり する過程で行き詰ると予想される部分について簡単に解説します. このスライドの目的は自主学習のサポートであり,説明が簡略化さ れています.完全な理解には自主学習が必要なので注意してくださ い. 目次 webプロキシとは 何を実装すればよいのか 実装方法の例 webサーバの特定方法 実装をする上での注意 webプロキシとは 一般的な通信は直接通信 webサーバ ブラウザ webプロキシとは proxy = 「代理」 webサーバとのデータのやりとりを中継する webサーバ ブラウザ プロキシ $./proxy 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ proxy側 listen() プロキシ $./proxy webサーバ listen() 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ proxy側 listen() プロキシ $./proxy ブラウザ側の connect() webサーバ listen() 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy プロキシ側で accept() webサーバ listen() 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ ブラウザからの リクエスト プロキシ $./proxy webサーバ listen() 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy リクエストから webサーバを特定 webサーバ listen() 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ webサーバ listen() $./proxy webサーバへの connect() 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy webサーバが accept() 何を実装すればよいのか プログラムの流れ ブラウザ プロキシ $./proxy ブラウザからの リクエストを 転送 webサーバ 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy webサーバからの レスポンス 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy webサーバからの レスポンスを 転送 何を実装すればよいのか プログラムの流れ webサーバ ブラウザ プロキシ $./proxy ソケットクローズ 何を実装すればよいのか HTTP1.0では 1リクエスト + 1レスポンス = 1コネクション 各リクエストごとに接続を確立します. 何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ $./proxy 何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ proxy側 listen() プロキシ $./proxy ブラウザ側の connect() webサーバ listen() 何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ $./proxy プロキシ側で accept() webサーバ listen() 何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ listen用ソケット は残しておく プロキシ webサーバ listen() $./proxy 別スレッド,または別プロセス accept()したら 後は並列処理に任せる proxy 何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ listen用ソケット は残しておく プロキシ webサーバ listen() $./proxy 別スレッド,または別プロセス proxy 何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ ブラウザ側の connect() webサーバ listen() $./proxy 別スレッド,または別プロセス proxy 何を実装すればよいのか さらに,ブラウザからのconnectを複数受け付けるには webサーバ ブラウザ プロキシ プロキシ側で accept() webサーバ listen() $./proxy 別スレッド,または別プロセス 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) スレッドorプロセス によって作成した子の中で Selectを用いればよい 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; } ※あくまでも一例です.また,引数や実装方法が簡略化されています. 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プロキシプログラムは 1. ブラウザからのconnect()をaccept()する 2. ブラウザとの通信用のソケットを並列処理に持っていく 以下,並列処理 1. ブラウザからリクエストを受け取る 2. ブラウザのリクエストからwebサーバを特定する 3. webサーバとの通信用ソケットを作成し,connect()する 4. ブラウザのリクエスト,webサーバからのレスポンスを転送す る(このとき,リクエストはあらかじめ適切に変換しておく) 5. ソケットを閉じる
© Copyright 2024 ExpyDoc