[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

情報処理IIIA(Javaプログラミング入門)第13回

目次 索引
13.1 ネットワーク・インターフェース
13.1.1 URLクラス
13.1.2 クライアントとサーバ
13.1.3 ソケットによる通信
13.1.4 Javaによるメールの送信
13.1.5 Javaによるホームページへのアクセス
13.1.6 Javaによるサーバの例
13.2 アンケート13

13.1 ネットワーク・インターフェース

13.1.1 URLクラス

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ブラウザが出来上がると言うわけです。

13.1.2 クライアントとサーバ

ネットワーク・アプリケーションの多くは、クライアント/サーバモデルに基づいています。 ここで、 クライアントclient )とは、サービスを要求する側のプログラムです。 また、 サーバserver )とは、サービスを提供する側のプログラムです。

サーバは、通常いつも稼動していて、クライアントからの要求を待っています。 クライアントは、要求が発生しますと、まずネットワークを通してサーバホストを探し、サーバプログラムとコネクション(接続)を張ります。 そして、サーバとクライアントとの間で必要なデータ交換を行います。 要求が満たされますと、コネクションは切断されます。 なお、このデータ交換に関する規約を、 プロトコルprotocol )とよびます。

サーバホストでは、普通複数のサーバプログラムが稼動しています。 これらのプログラムを区別するのがポート番号です。 サーバプログラムとの接続は、ホスト(のIPアドレス)とポート番号を指定して行います。 なお、代表的なネットワーク・アプリケーションは、それぞれ固有のポート番号を持っています。

13.1.3 ソケットによる通信

Javaでクライアントプログラムやサーバプログラムを作るには、 ソケットsocket )とよばれるものを利用します。 ソケットとは、プログラムとネットワークの接点となる機構です。 プログラムでは、ソケットを生成し、そこから入力ストリームと出力ストリームを生成するように書きます。 このプログラムを実行しますと、入力ストリームからデータを読み込むことが、ネットワークからのデータの受信となります。 同様に、出力ストリームへデータを書き込むことが、ネットワークへのデータの送信となるのです。 ファイルの読み書きと同じ要領で、ネットワークに対するデータの送受信ができるのです。

具体的には、組み込みのクラスである Socket クラスと ServerSocket クラスを用いて、ソケットを取り扱います。

13.1.4 Javaによるメールの送信

クライアントの例として、はじめにメールの送信を取り上げます。 メールの送信は、基本的にSMTP(Simple Mail Transfer Protocol)というプロトコルに基づいて行われます。 SMTPは25番ポートを使用します。 このプロトコルにおけるデータの流れは、おおむね次の通りです。

表 13.1  SMTPにおけるデータの流れ
クライアント 方向 サーバ 意味
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%

13.1.5 Javaによるホームページへのアクセス

クライアントの次の例は、ホームページへのアクセスです。 ホームページへのアクセスは、HTTP(HyperText Transfer Protocol)というプロトコルに基づいて行なわれます。 HTTPは80番ポートを使用します。 このプロトコルにおけるデータの流れは、おおむね次の通りです。

表 13.2  HTTPにおけるデータの流れ
クライアント 方向 サーバ 意味
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%

13.1.6 Javaによるサーバの例

サーバの例としまして、アクセス・カウンタを作ります。 これは、ホームページのアクセス・カウンタを単純化したもので、単にアクセス数のメッセージをクライアントに送るものです。 プロトコルは次のようにします。

表 13.3  アクセス・カウンタにおけるデータの流れ
クライアント 方向 サーバ 意味
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を押してサーバプログラムを強制終了させます。


13.2 アンケート13

今日の授業内容に関して、アンケートを行ないます。 以下の質問に答え、回答をkonishi@twcu.ac.jpあてにメールで送ってください。 メールには、学生番号、氏名、科目名、授業日(12/13)を明記してください。 アンケートに回答しますと、今日の授業に出席したものと見なします。

  1. Javaで実現できそうで、おもしろい、あるいは役に立つ、ネットワーク・アプリケーションを考えてください。 このアプリケーションは、クライアント/サーバモデルに基づくものとします。 クライアントとサーバがそれぞれどのような役割を果たすか、またクライアントとサーバの間でどのようなデータ交換が行なわれるかについても触れてください。 どうしても思いつかない人は、上記のアクセス・カウンタを改造して人気投票システムにするにはどうすればよいかを考えてください。 このシステムは、あらかじめ候補者に番号を付けておき、番号を送信しますと、これまでの投票結果が受信されるものです。

[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2002年1月8日更新
konishi@twcu.ac.jp
Copyright (C) 2002 Zenjiro Konishi. All rights reserved.