ネットワークプログラミング 田村寿浩馬建華
目次 サーバーの概要 構成 ネットワークのレイヤー TCPを利用した通信 Javaによるネットワークプログラミング
サーバーとは サーバーとはクライアントからの要求に対して何らかのサービスを提供する役割を果たしているプログラム又は稼働させている機器を表す 例 :Web サーバー ウェブブラウザの URL に指示された Web サーバ内に存在する HTML ドキュメントの各種動作をクライアントから接続された HTTP に則った TCP/IP ソケットストリーム (HTTP コネクション ) に送信する
Web サーバの構成 黄研究室のサーバの例 IP アドレス :133.25.82.204 ドメイン名 :rhserver.k.hosei.ac.jp ソフトウェア :Windows Server 2008 IP(Internet Protocol) IP アドレスを用いてネットワーク上の PC の位置を表すもの DNS(Domain Name System) ドメイン名と IP アドレスを関連付けるシステム
ポート番号とは 通信のサービスを特定するための番号 No Protocol サービス 20 ftp-data ファイル転送 ( データ本体 ) 21 ftp ファイル転送 ( コントロール ) 22 ssh シェル :SSH( セキュア ) 23 telnet シェル :telnet 25 smtp メール送受信 :SMTP 53 domein DNS 80 http WWW 110 pop3 メール受信 (POP) 上記はよく利用されるポート番号とプロトコル サービスによってデータの送受信の受け口が分かれている 一部のオンラインゲームではポートの開放が必要だが 悪意のある接続を許すもとにもなる
ネットワークのレイヤー ネットワークは各層に分かれ データの送受信を行う 各層に役割を分担することで拡張性や保守性を高めている 名前説明例 アプリケーション層 具体的な通信サービス HTTP FTP Telnet プレゼンテーション層 データの表現方法に関する規定 FTP Telnet セッション層 通信開始から終了までの手順 NetBIOS ASP トランスポート層 エラー訂正などの通信管理 TCP UDP ネットワーク層 通信経路の選択 IP ARP データリンク層 通信機器間の信号の受け渡し イーサネット トークンリング 物理層 物理的な回線や機器 電話線 光ケーブル
TCP/IP まとめ 宛名等宛先等内容宛名等内容 :www.yahoo.co.jp :80 (GET index.html HTTP/1.1 (GET 宛先ポート index.html 200 OK :192.168.1.20 :3000 HTTP/1.1 宛先ポート 200 OK :80 :3000 :192.168.1.20 :3000 HTTP1.1) HTTP1.1) 自分ポート :www.yahoo.co.jp :80 <HTML> 自分ポート :3000 :80 <HTML> 宛名等内容宛先ポート HTTP/1.1 (GET index.html 200 :80 :3000 OK 自分ポート <HTML> HTTP1.1) :3000 :80 内容 HTTP/1.1 (GET index.html 200 OK <HTML> HTTP1.1) HTTP TCP HTTP IP TCP HTTP TCP HTTP 内容 HTTP/1.1 (GET index.html 200 OK <HTML> HTTP1.1) HTTP WEB サーバの待ち受けポート番号は 80 世界中で統一されている FTP は 21 POP は 110 等々 送信元のポート番号は Windows が空いているポートを勝手に選択する例 :3000
TCP を利用した通信 TCP を利用したプロトコルとして以下の 3 つを挙げる Telnet FTP HTTP
接続するサーバーの準備 Telnet FTP の接続テストをするために FTP サーバー Cerberus FTP Server を導入した
Telnet とは? Telnet(Telecommunication network) とは汎用的な双方向 8 ビット通信を提供する端末 プロセス間の通信プロトコル ポート 23 を利用するが他のポートの指定ができ TCP サービスのテストにも用いられる セキュリティの問題があるため現在では 利用が推奨されない コマンドプロンプトで Telnet 通信をしてみましょう
コマンドプロンプトによる Telnet 通信 Windows7 8 では Telnet クライアントの機能の有効化をしないと使えない
コマンドプロンプトによる Telnet 通信コマンドプロンプトを起動し telnet と入力し Telnet クライアントを起動する 起動後に help と入力するとコマンド一覧が見れます
Telnet でサーバーへ接続 Cerberus サーバーに接続するために open localhost 21 と指定する localhost は自分のパソコンのホスト名
Telnet でサーバーへ接続 接続に成功した時の出力 コンソール側 Cerberus 側
Telnet でサーバーへ接続 ユーザー名とパスワードを入力しログイン が telnet ではファイル転送できないのでログイン出来るかどうかの確認程度に使われます
FTP FTP(File Transfer Protocol) とはネットワークでファイルの転送を行うための通信プロトコル FTP ファイルサーバやウェブページからクライアントへのファイルのアップロード ダウンロードに使われる ポート 21 を使用する コマンドプロンプトで FTP 通信をしてみましょう
コマンドプロンプトによる FTP 通 信コマンドプロンプトを起動しftpと入力しFTPクライアントを起動する 起動後に help と入力するとコマンド一覧が見れます
コマンドプロンプトによる FTP 通 信 Cerberusサーバーに接続するために open localhost と指定しユーザー名とパスワードも入力
ディレクトリの確認 Current ディレクトリを確認すると Root ディレクトリにいることがわかる
ディレクトリの作成 mkdir コマンドで network ディレクトリを作成したところ
ファイルのアップロード put < ファイル名 > < 保存する名前 > でファイルをアップロードする
ファイルのダウンロード gut < ファイル名 > < 保存する名前 > でファイルをダウンロードする この例では C: Users admin に保存される
HTTP HTTP(Hypertext Transfer Protocol) とは Web ブラウザと Web サーバの間で HTML や XML などの Hypertext の送受信に用いられる通信プロトコル クライアントがサーバーにリクエストを送り サーバーがレスポンスを返す仕組み ポート 80 を使用する
Java によるネットワークプログラ ミング Telnet, FTP は ApacheCoomons のライブラリを使うと楽 http://commons.apache.org/proper/commonsnet/index.html
CommonsNet の導入 左の Download から 3.3 をダウンロードする
Java による Telnet 通信 TelnetClient クラスの connect メソッドを呼び出すだけで簡単にサーバーに接続できる TelnetClient tc = new TelnetClient(); // 接続先 String remoteip = "localhost"; // 接続ポート int remoteport = 21; // 接続 tc.connect(remoteip, remoteport);
Java による Telnet 通信 今回用意した FTP サーバーではメッセージを返さないので AYT(Are you there) コマンドを入力しても返ってこない /(^o^)\
Java による FTP 通信 FTPClient クラスの connect メソッドを呼び出すだけで簡単にサーバーに接続できる // FTP サーバーに接続するクラス FTPClient fp = new FTPClient(); // サーバを指定してアクセス fp.connect("localhost"); // ユーザー名とパスワードを指定しログイン fp.login("root", "password");
Java による FTP 通信 ログイン後は FileStream クラスを使ってファイルのアップ ダウンロードを行う FileOutputStream os = null; FileInputStream is = null; // ファイルダウンロード os = new FileOutputStream( aaa.txt"); fp.retrievefile("/network/sample2.txt", os); os.close(); // ファイルアップロード is = new FileInputStream("c:/a.txt"); fp.storefile("/network/sample2.txt", is); is.close();
ファイルを送受信した際のログ
Java によるネットワークプログラミング ライブラリなどを使わない場合は Socket を使って通信を行う 例としてチャットプログラムを作成する Socket : IP とポート番号を合わせたアドレス
サーバー側の処理 1. ServerSocket を生成しポート番号と最大接続人数を設定する 2. クライアントの接続を待つ 3. クライアントと通信できるようにストリームオブジェクトを生成する 4. ストリームオブジェクトを介して通信を行う 5. コネクションを閉じる
クライアント側の処理 1. Socket を生成しサーバーに接続する 2. クライアントと通信できるようにストリームオブジェクトを生成する 3. ストリームオブジェクトを介して通信を行う 4. コネクションを閉じる
クライアントをサーバーに接続する サーバー側 クライアント側 // 使用するポート番号 ServerSocket server = new ServerSocket(2815,50); // 接続先サーバーのホスト名 private static final String HOST = "localhost"; while (!server.isclosed()) { // クライアントの接続を待つ Socket client = server.accept(); // ユーザーオブジェクトを生成 ChatClientUser user = new ChatClientUser(client); adduser(user); // 接続先ポート番号 private static final int PORT = 2815; // クライアントソケット private Socket socket; socket = new Socket(HOST, PORT);
メッセージの送受信 ( サーバー側 ) 送信 OutputStream output = socket.getoutputstream(); PrintWriter writer = new PrintWriter(output); // メッセージの送信 writer.println(message); writer.flush(); 受信 InputStream input = socket.getinputstream(); BufferedReader reader = new BufferedReader(new InputStreamReader( input)); // ユーザーのメッセージ送信を確認 while (!socket.isclosed()) { String line = reader.readline(); System.out.println("INPUT=" + line); String[] msg = line.split(" ", 2); String msgname = msg[0]; String msgvalue = (msg.length < 2? "" : msg[1]); // メッセージの種類に合わせて処理を分ける reachedmessage(msgname, msgvalue);
メッセージの送受信 ( サーバー側 ) 送信 OutputStream output = socket.getoutputstream(); PrintWriter writer = new PrintWriter(output); // メッセージの送信 writer.println(message); writer.flush(); 実はサーバーと同じ 受信 InputStream input = socket.getinputstream(); BufferedReader reader = new BufferedReader(new InputStreamReader( input)); // ユーザーのメッセージ送信を確認 while (!socket.isclosed()) { String line = reader.readline(); String[] msg = line.split(" ", 2); String msgname = msg[0]; String msgvalue = (msg.length < 2? "" : msg[1]); // メッセージの種類に合わせて処理を分ける reachedmessage(msgname, msgvalue);
デモ クライアントとサーバーで設定しているポート番号が違っていたり サーバーが起動する前にクライアントを動かすとエラーになるので注意
import java.io.*; import java.net.*; /** Http プロトコルによるソース表示 **/ public class HttpBySocket { public static void main(string args[]) { String host = "rat.cis.k.hosei.ac.jp"; int port = 80; String url = "http://rat.cis.k.hosei.ac.jp/", str; try { // ソケットの作成 Socket sock = new Socket(host, port); BufferedReader sockin = new BufferedReader( new InputStreamReader( sock.getinputstream())); BufferedWriter sockout = new BufferedWriter( new OutputStreamWriter( sock.getoutputstream())); // HTTP リクエスト送信 sockout.write("get " + url + " HTTP/1.1 r n"); sockout.write("host: " + host + " r n"); sockout.write("connection: close r n"); sockout.write(" r n"); sockout.flush(); Web ページのソースの取得 Socket を使って RAT のページのソースを取得する // HTTP レスポンス受信 while ((str = sockin.readline())!= null) { System.out.println(str); } // ソケットのクローズ sockout.close(); sockin.close(); sock.close(); } catch (Exception ex) { ex.printstacktrace(); } } }
Web ページのソースの取得 ソースの取得はできるが Http リクエストが面倒 ここからソース
Web ページのソースの取得 URLConnection を使うとソースを取得が楽 import java.io.*; import java.net.*; /** Http プロトコルによるソース表示 **/ public class URLConnectionTest { public static void main(string args[]) { String url = "http://rat.cis.k.hosei.ac.jp/"; URL urlobj; HttpURLConnection urlcon; BufferedReader urlin; String str; try { urlobj = new URL(url); // URL 接続 urlcon = (HttpURLConnection) urlobj.openconnection(); urlcon.setrequestmethod("get"); urlin = new BufferedReader(new InputStreamReader( urlcon.getinputstream())); // HTML ソースの表示 while ((str = urlin.readline())!= null) { System.out.println(str); } // URL 切断 urlin.close(); urlcon.disconnect(); } catch (Exception ex) { ex.printstacktrace(); } } }
実行結果
その他の通信 紹介した Socket 通信は一旦繋ぐと常につなぎっぱなしになるが DatagramPacket を使うとパケットによって通信を行う
参考文献 関連するコマンドの解説 http://ykr414.com/dos/dos03.html Windows7 で Telnet 接続 http://axela5004.blog74.fc2.com/blog-entry- 422.html Java ネットワークプログラミング http://ash.jp/java/java_http.htm Socket と URLConnection http://news.mynavi.jp/column/java/054/index.html
参考文献 Java プログラミング Vol.2 古い本ですが Socket 通信を使った五目並べや DatagramPacket の例も載っています