目次 | 索引 |
---|---|
Javaには、ホームページへのアクセスが簡単に行える機能があります。 あたかもローカルファイルの内容を読み込むように、ネットワーク上のホームページの内容が読み込めるのです。
組み込みのクラスである
URL
クラスを用いますと、ホームページにアクセスできます。
URL
クラスのインスタンス
url
とインスタンスメソッド
openStream()
で式
url.openStream()
を作りますと、これが入力ストリームになります。
この入力ストリームからデータを読み込みますと、ホームページの内容が取り出せるのです。
なお、コンストラクタ
URL
の引数は、URL/URIを表す文字列となります。
以下のプログラムは、本学のトップページの内容(HTML)を読み込み、それを画面に出力するものです。
/* 1*/ import java.io.*; /* 2*/ import java.net.*; /* 3*/ /* 4*/ class URLTest { /* 5*/ public static void main (String[] args) throws IOException { /* 6*/ URL u = new URL("http://www.twcu.ac.jp/index.html"); /* 7*/ DataInputStream dis; /* 8*/ dis = new DataInputStream(u.openStream()); /* 9*/ String s; /*10*/ for (s = dis.readLine(); s != null; s = dis.readLine()) { /*11*/ System.out.println(s); /*12*/ } /*13*/ dis.close(); /*14*/ } /*15*/ }
b00a001@Ampere:~/java% java URLTest HTTP/1.1 200 OK Date: Thu, 13 Dec 2001 00:15:00 GMT ... Content-Type: text/html <HTML> <HEAD> <TITLE>TWCU</TITLE> </HEAD> <BODY> ... </BODY> </HTML> b00a001@Ampere:~/java%
2行目は、これからネットワーク関係のクラスを用いるという意味です。
6行目で、
URL
クラスのインスタンスを生成します。
8行目で、そのインスタンスから入力ストリームを作り、そこからフィルタ付き入力ストリームを生成します。
後はファイルの内容を読み込むプログラムと同じです。
このプログラムで取り出されたデータは、大きく二つに分かれます。 前半は、内容の長さや種類など、ホームページに関する情報です。 ホームページの内容自身は後半になります。
このプログラムは、ホームページの内容をただ取り出しているだけです。 それを解析し、内容をグラフィカルに表示するプログラムを追加すれば、WWWブラウザが出来上がると言うわけです。
ネットワーク・アプリケーションの多くは、クライアント/サーバモデルに基づいています。 ここで、 クライアント ( client )とは、サービスを要求する側のプログラムです。 また、 サーバ ( server )とは、サービスを提供する側のプログラムです。
サーバは、通常いつも稼動していて、クライアントからの要求を待っています。 クライアントは、要求が発生しますと、まずネットワークを通してサーバホストを探し、サーバプログラムとコネクション(接続)を張ります。 そして、サーバとクライアントとの間で必要なデータ交換を行います。 要求が満たされますと、コネクションは切断されます。 なお、このデータ交換に関する規約を、 プロトコル ( protocol )とよびます。
サーバホストでは、普通複数のサーバプログラムが稼動しています。 これらのプログラムを区別するのがポート番号です。 サーバプログラムとの接続は、ホスト(のIPアドレス)とポート番号を指定して行います。 なお、代表的なネットワーク・アプリケーションは、それぞれ固有のポート番号を持っています。
Javaでクライアントプログラムやサーバプログラムを作るには、 ソケット ( socket )とよばれるものを利用します。 ソケットとは、プログラムとネットワークの接点となる機構です。 プログラムでは、ソケットを生成し、そこから入力ストリームと出力ストリームを生成するように書きます。 このプログラムを実行しますと、入力ストリームからデータを読み込むことが、ネットワークからのデータの受信となります。 同様に、出力ストリームへデータを書き込むことが、ネットワークへのデータの送信となるのです。 ファイルの読み書きと同じ要領で、ネットワークに対するデータの送受信ができるのです。
具体的には、組み込みのクラスである
Socket
クラスと
ServerSocket
クラスを用いて、ソケットを取り扱います。
クライアントの例として、はじめにメールの送信を取り上げます。 メールの送信は、基本的にSMTP(Simple Mail Transfer Protocol)というプロトコルに基づいて行われます。 SMTPは25番ポートを使用します。 このプロトコルにおけるデータの流れは、おおむね次の通りです。
クライアント | 方向 | サーバ | 意味 |
---|---|---|---|
← | 220 ...\n |
コネクション確立 | |
HELO clienthost\n |
→ | クライアントホストの通知 | |
← | 250 ...\n |
完了 | |
MAIL FROM: < sender>\n |
→ | 差出人アドレスの通知 | |
← | 250 ...\n |
完了 | |
RCPT TO: < recipient>\n |
→ | 宛先アドレスの通知 | |
← | 250 ...\n |
完了 | |
DATA\n |
→ | メッセージ開始 | |
← | 354 ...\n |
入力待ち | |
text\n |
→ | メッセージ | |
... | ... | ... | |
text\n |
→ | メッセージ | |
.\n |
→ | メッセージ終了 | |
← | 250 ...\n |
完了 | |
QUIT\n |
→ | コネクション切断 | |
← | 221 ...\n |
切断完了 |
以下のプログラムは、自分あてにテストメールを送るものです。 なお、訳も分らずにメールを送ることは、受取人やシステム管理者に迷惑をかけることになります。 このプログラムを実行するには、内容を十分理解した上で行ってください。
/* 1*/ import java.io.*; /* 2*/ import java.net.*; /* 3*/ /* 4*/ class MailTest { /* 5*/ public static void main (String[] args) throws IOException { /* 6*/ String serverHost; /* 7*/ serverHost = InetAddress.getByName("smtp").getHostName(); /* 8*/ int port = 25; /* 9*/ String clientHost; /*10*/ clientHost = InetAddress.getLocalHost().getHostName(); /*11*/ String sender = System.getProperty("user.name"); /*12*/ String recipient = System.getProperty("user.name"); /*13*/ String message = "This is a test message"; /*14*/ Socket sock = new Socket(serverHost, port); /*15*/ DataInputStream dis; /*16*/ dis = new DataInputStream(sock.getInputStream()); /*17*/ PrintStream prs; /*18*/ prs = new PrintStream(sock.getOutputStream()); /*19*/ prs.println("HELO " + clientHost); /*20*/ System.out.println(dis.readLine()); /*21*/ prs.println("MAIL FROM: <" + sender + ">"); /*22*/ System.out.println(dis.readLine()); /*23*/ prs.println("RCPT TO: <" + recipient + ">"); /*24*/ System.out.println(dis.readLine()); /*25*/ prs.println("DATA"); /*26*/ System.out.println(dis.readLine()); /*27*/ prs.println("From: <" + sender + ">"); /*28*/ prs.println("To: <" + recipient + ">"); /*29*/ prs.println(); /*30*/ prs.println(message); /*31*/ prs.println("."); /*32*/ System.out.println(dis.readLine()); /*33*/ prs.println("QUIT"); /*34*/ System.out.println(dis.readLine()); /*35*/ dis.close(); /*36*/ prs.close(); /*37*/ sock.close(); /*38*/ } /*39*/ }
b00a001@Ampere:~/java% java MailTest 220 twcu.ac.jp ESMTP ... 250 twcu.ac.jp ... 250 <b00a001>... Sender ok 250 <b00a001>... Recipient ok 354 Enter mail, ... 250 AAA99999 Message accepted for delivery b00a001@Ampere:~/java%
クライアントの次の例は、ホームページへのアクセスです。 ホームページへのアクセスは、HTTP(HyperText Transfer Protocol)というプロトコルに基づいて行なわれます。 HTTPは80番ポートを使用します。 このプロトコルにおけるデータの流れは、おおむね次の通りです。
クライアント | 方向 | サーバ | 意味 |
---|---|---|---|
GET pathname\n |
→ | 内容の取得 | |
← | text\n |
内容 | |
... | ... | ... | |
← | text\n |
内容 |
次のプログラムは、本学のトップページの内容を読み込み、それを画面に出力するものです。 URLTest.java と比べてみてください。
/* 1*/ import java.io.*; /* 2*/ import java.net.*; /* 3*/ /* 4*/ class HomePageTest { /* 5*/ public static void main (String[] args) throws IOException { /* 6*/ String serverHost; /* 7*/ serverHost = InetAddress.getByName("www").getHostName(); /* 8*/ int port = 80; /* 9*/ String path = "/index.html"; /*10*/ Socket sock = new Socket(serverHost, port); /*11*/ DataInputStream dis; /*12*/ dis = new DataInputStream(sock.getInputStream()); /*13*/ PrintStream prs; /*14*/ prs = new PrintStream(sock.getOutputStream()); /*15*/ prs.println("GET " + path); /*16*/ String s; /*17*/ for (s = dis.readLine(); s != null; s = dis.readLine()) { /*18*/ System.out.println(s); /*19*/ } /*20*/ dis.close(); /*21*/ prs.close(); /*22*/ sock.close(); /*23*/ } /*24*/ }
b00a001@Ampere:~/java% java HomePageTest <HTML> <HEAD> <TITLE>TWCU</TITLE> </HEAD> <BODY> ... </BODY> </HTML> b00a001@Ampere:~/java%
サーバの例としまして、アクセス・カウンタを作ります。 これは、ホームページのアクセス・カウンタを単純化したもので、単にアクセス数のメッセージをクライアントに送るものです。 プロトコルは次のようにします。
クライアント | 方向 | サーバ | 意味 |
---|---|---|---|
← | Connected.\n |
コネクション確立 | |
Count.\n |
→ | アクセス数の取得 | |
← | text\n |
アクセス数 |
サーバプログラムは以下の通りです。 なお、サーバを起動するには、普通システム管理者の許可が必要です。 内容を理解した上で、実験の範囲内で行なってください。
/* 1*/ import java.io.*; /* 2*/ import java.net.*; /* 3*/ /* 4*/ class ServerTest { /* 5*/ public static void main (String[] args) throws IOException { /* 6*/ int port = Integer.parseInt(args[0]) + 10000; /* 7*/ ServerSocket svsock = new ServerSocket(port); /* 8*/ Socket sock; /* 9*/ DataInputStream dis; /*10*/ PrintStream prs; /*11*/ int count = 0; /*12*/ while (true) { /*13*/ sock = svsock.accept(); /*14*/ dis = new DataInputStream(sock.getInputStream()); /*15*/ prs = new PrintStream(sock.getOutputStream()); /*16*/ prs.println("Connected."); /*17*/ System.out.println(dis.readLine()); /*18*/ count++; /*19*/ prs.print("This is the " + count); /*20*/ prs.println("st/nd/rd/th access."); /*21*/ dis.close(); /*22*/ prs.close(); /*23*/ sock.close(); /*24*/ } /*25*/ } /*26*/ }
クライアントプログラムは次の通りです。
/* 1*/ import java.io.*; /* 2*/ import java.net.*; /* 3*/ /* 4*/ class ClientTest { /* 5*/ public static void main (String[] args) throws IOException { /* 6*/ int port = Integer.parseInt(args[0]) + 10000; /* 7*/ Socket sock = new Socket("localhost", port); /* 8*/ DataInputStream dis; /* 9*/ dis = new DataInputStream(sock.getInputStream()); /*10*/ PrintStream prs; /*11*/ prs = new PrintStream(sock.getOutputStream()); /*12*/ System.out.println(dis.readLine()); /*13*/ prs.println("Count."); /*14*/ System.out.println(dis.readLine()); /*15*/ dis.close(); /*16*/ prs.close(); /*17*/ sock.close(); /*18*/ } /*19*/ }
はじめに、サーバプログラムを起動します。
b00a001@Ampere:~/java% java ServerTest `id -u`
クライアントからの要求を待っていますので、この端末エミュレータではクライアントプログラムは動かせません。 もう一つ端末エミュレータを開きまして、クライアントプログラムを実行します。
b00a001@Ampere:~/java% java ClientTest `id -u` Connected. This is the 1st/nd/rd/th access. b00a001@Ampere:~/java% java ClientTest `id -u` Connected. This is the 2st/nd/rd/th access. b00a001@Ampere:~/java% java ClientTest `id -u` Connected. This is the 3st/nd/rd/th access. b00a001@Ampere:~/java%
確かに、アクセス数が返ってきます。 ここでサーバプログラムの端末エミュレータに戻りますと、
b00a001@Ampere:~/java% java ServerTest `id -u` Count. Count. Count. ^C b00a001@Ampere:~/java%
クライアントプログラムからの接続があったことが分かります。 最後に、Ctrl-Cを押してサーバプログラムを強制終了させます。
今日の授業内容に関して、アンケートを行ないます。 以下の質問に答え、回答をkonishi@twcu.ac.jpあてにメールで送ってください。 メールには、学生番号、氏名、科目名、授業日(12/13)を明記してください。 アンケートに回答しますと、今日の授業に出席したものと見なします。