Java で HTTP クライアントを作ってみよう (1)

前へ << TCP/IP エラー処理 connect 編 Java で HTTP クライアントを作ってみよう (2) >> 次へ

Socket クラス

Java における最も基礎的なネットワーク関連のクラスは Socket クラスです。 Socket クラスを使って HTTP クライアントを作成してみます。

HTTP クライアントの使用方法ですが、まず

% javac HttpClientSocket.java
とコンパイルすることで HttpClientSocket.class が生成されます。そして
% java HttpClientSocket
として実行します。実行に成功すれば、
HTTP/1.1 200 OK
Date: Sat, 05 Mar 2005 06:19:10 GMT
Server: Apache
(略)
Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
(略)
などと、ヘッダとボディをそのまま標準出力に出力します。

ソース

HttpClientSocket.java

    1: import java.net.*;
    2: import java.io.*;
    3: 
    4: /**
    5:  * Java HTTP クライアントサンプル - Socket 版 -
    6:  *
    7:  * @author 68user http://X68000.q-e-d.net/~68user/
    8:  */
    9: public class HttpClientSocket {
   10:     public static void main(String[] args){
   11:         String host = "www.jp.FreeBSD.org";
   12:         int port = 80;
   13:         String path = "/index.html";
   14: 
   15:         Socket socket;
   16:         BufferedReader reader;
   17:         BufferedWriter writer;
   18: 
   19:         try {
   20:             socket = new Socket(host, port);
   21:             reader =
   22:                 new BufferedReader(new InputStreamReader(socket.getInputStream()));
   23:             writer =
   24:                 new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
   25: 
   26:             writer.write("GET " + path + " HTTP/1.0\r\n");
   27:             writer.write("Host: " + host + ":" + port + "\r\n");
   28:             writer.write("\r\n");
   29:             writer.flush();
   30: 
   31:             while (true){
   32:                 String line = reader.readLine();
   33:                 if ( line == null ){
   34:                     break;
   35:                 }
   36:                 System.out.println(line);
   37:             }
   38:             reader.close();
   39:             writer.close();
   40:             socket.close();
   41: 
   42:         } catch (UnknownHostException e){
   43:             e.printStackTrace();
   44:         } catch (IOException e){
   45:             e.printStackTrace();
   46:         }
   47:     }
   48: }

ソース解説

   11:         String host = "www.jp.FreeBSD.org";
   12:         int port = 80;
   13:         String path = "/index.html";
まず、ホスト名・ポート番号・パスを指定します。 この例では http://www.jp.FreeBSD.org:80/index.html を取得します。
Java で getservbyname 的なメソッド ("http" から 80 を取得するもの) はどこにあるんだろう?

   15:         Socket socket;
   20:             socket = new Socket(host, port);
Socket オブジェクトを生成します。このときサーバに接続を行います。 引数にはホスト名とポート番号を指定します。

ホスト名から IP アドレスへの変換は Socket クラスが内部で行ってくれますが、 もし自分でやりたいなら

InetAddress inetaddr = InetAddress.getByName(hostname);
Socket socket = new Socket(inetaddr, port);
とします。
これで Socket オブジェクトは生成されましたが、まだ入出力を行うための出入口がありません。 以下のようにして入力用の BufferedReader と出力用の BufferedWriter を生成します。
   16:         BufferedReader reader;
   17:         BufferedWriter writer;
   21:             reader =
   22:                 new BufferedReader(new InputStreamReader(socket.getInputStream()));
   23:             writer =
   24:                 new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
Socket#getInputStream で、入力用のバイトストリームである InputStream オブジェクトを取得します。

InputStream は単なるバイトデータ用のストリームなので、InputStreamReader クラスを介して、 文字ストリームに変換します。 さらにバッファリングを行う BufferedReader クラスを介して、実行効率を高めます。

出力用の BufferedWriter オブジェクトも同様に取得します。


   26:             writer.write("GET " + path + " HTTP/1.0\r\n");
   27:             writer.write("Host: " + host + ":" + port + "\r\n");
   28:             writer.write("\r\n");
   29:             writer.flush();
サーバに対して、
GET /index.html HTTP/1.0(CRLF)
Host: www.jp.FreeBSD.org:80(CRLF)
(CRLF)
というリクエストを送信します。BufferedWriter がバッファリングしているため、 write しただけではデータは送信されませんので、最後にバッファを flush します。
   31:             while (true){
   32:                 String line = reader.readLine();
   33:                 if ( line == null ){
   34:                     break;
   35:                 }
   36:                 System.out.println(line);
   37:             }
BufferedReader から 1行取得し、標準出力に出力します。 ストリームの終端に達したら BufferedReader#readLine は null を返すので、 それまでループを続けます。
   38:             reader.close();
   39:             writer.close();
   40:             socket.close();
最後に BufferedReader・BufferedWriter・Socket をクローズしておしまいです。
エラー処理について解説しておきます。

このプログラムで発生する例外は UnknownHostException と IOException の 2つです。 UnknownHostException は

   20:             socket = new Socket(host, port);
で発生する可能性があります。典型的なのは存在しないホスト名に接続しようとしたときです。

IOException は接続を行う部分と入出力を行う部分の全てで発生する可能性があります。

このプログラムでは、エラー発生時は以下のようにスタックトレースを表示しています。 Java のような例外機構がある言語はエラー処理が楽でいいですね。

   19:         try {
   42:         } catch (UnknownHostException e){
   43:             e.printStackTrace();
   44:         } catch (IOException e){
   45:             e.printStackTrace();
   46:         }
前へ << TCP/IP エラー処理 connect 編 Java で HTTP クライアントを作ってみよう (2) >> 次へ

ご意見・ご指摘は Twitter: @68user までお願いします。