はじめに
こんにちは。
スッキリわかるJava入門 実践編の学習を進めています。
この学習記録を備忘録として残しながら、自身の理解を深めたいと思っています。
今回は第2部「外部資源へのアクセス」/ 第8章「ネットワークアクセス」について学びました。
Javaのネットワーク機能は、URLクラスによる手軽なWebページ取得から、Socketによる低水準通信、HttpClientによるWebAPI連携まで、用途に応じて抽象度の異なるAPIが用意されています。
この記事が、同じくJavaの学習をしている人にとっても参考になりましたら幸いです。
参考書籍について
- 書籍名:スッキリわかるJava入門 実践編
- 著者:中山清喬
- 出版社:インプレス
目次
1. 本章の要点
ネットワークAPIの全体像
Javaのネットワーク機能は、抽象度の違う「高水準」と「低水準」のAPIに分かれています。
高水準API(java.net.URL)は手軽にWebページを取得でき、低水準APIはTCP/IP通信を細かく制御できます。
import java.io.*;
import java.net.URL;
public class UrlExample {
public static void main(String[] args) throws IOException {
URL url = new URL("https://example.com/");
// openStreamでWebページの内容を取り出すストリームを取得
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream(), "UTF-8"))) {
String line;
int count = 0;
while ((line = reader.readLine()) != null && count < 5) {
System.out.println(line);
count++;
}
}
}
}
// 出力例(先頭5行):
// <!doctype html>
// <html>
// <head>
// <title>Example Domain</title>
// ...
Socketを用いた低水準アクセス
Socketクラスを使うと、IPアドレスまたはホスト名とポート番号を指定してTCP/IP接続を行えます。
接続後のデータ書式や通信手順は、HTTPなどの上位プロトコルで決められています。
import java.io.*;
import java.net.Socket;
public class SocketClientExample {
public static void main(String[] args) throws IOException {
// example.comの80番ポートに接続
try (Socket socket = new Socket("example.com", 80);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
// HTTPのリクエストを手動で送信
writer.println("GET / HTTP/1.1");
writer.println("Host: example.com");
writer.println("Connection: close");
writer.println();
// レスポンスの先頭行を表示
System.out.println(reader.readLine());
}
}
}
// 出力例(環境やサイトの仕様によって異なる):
// HTTP/1.1 200 OK
// または
// HTTP/1.1 301 Moved Permanently(HTTPSへのリダイレクト)
サーバ側ソフトウェアの開発
ServerSocketクラスを使うと、指定したポート番号で接続を待ち受けるサーバプログラムを作成できます。
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
public static void main(String[] args) throws IOException {
// 8080番ポートで接続を待ち受ける
try (ServerSocket serverSocket = new ServerSocket(8080)) {
System.out.println("接続を待機しています...");
// 1件の接続を受け付けて、受信した内容をそのまま返す
try (Socket socket = serverSocket.accept();
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true)) {
String line = reader.readLine();
System.out.println("受信:" + line);
writer.println("エコー:" + line);
}
}
}
}
// 出力例(別のプログラムやtelnetなどで localhost:8080 に接続し「こんにちは」を送信した場合):
// 接続を待機しています...
// 受信:こんにちは
HTTPとWebAPI
HTTPは、1往復のリクエストとレスポンスで完結するプロトコルです。Webの通信の基盤になっています。
- リクエスト:メソッド(GET、POSTなど)、URL、ヘッダ、本文で構成
- レスポンス:ステータスコード、ヘッダ、本文で構成
- WebAPI:別のシステムからHTTPで接続を受け付け、連携して動作する仕組み
- REST:WebAPIの代表的な設計思想。URLで資源を表し、HTTPメソッドで操作を表す
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HttpClientExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
// GETリクエストを組み立てる
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/"))
.GET()
.build();
// レスポンスを受け取る
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
String body = response.body();
System.out.println("ステータス:" + response.statusCode());
// 本文が50文字未満の場合でも例外にならないよう、短い方の長さまで表示する
System.out.println("本文の先頭:" + body.substring(0, Math.min(50, body.length())));
}
}
// 出力例:
// ステータス:200
// 本文の先頭:<!doctype html><html><head><title>Example Domain</title>
Socketと高水準APIの使い分け
通常のWebページ取得やWebAPI連携はHttpClientなどの高水準APIを使う。
Socketは独自プロトコルの実装や、通信の仕組みを理解したいときに使う。
2. 自分なりの解釈
- 高水準APIで済む場面と低水準APIが必要な場面を見分けることが、ネットワーク処理では大切だとわかりました。
- HTTPはリクエストとレスポンスの組み合わせで成り立っていると知ると、WebAPIの仕組みが理解しやすくなりました。
- URLクラス、Socket、HttpClientのように、同じネットワーク通信でもAPIの抽象度が違うことがわかりました。
最後まで見ていただきありがとうございました。
次回は、第2部 / 第9章「データベースアクセス」について書く予定です。