5分でマスター!Javaソケット入門

Java_インターネットアクセスについて Java

Javaでネットワーク通信を書こうとすると、「ソケットのつなぎ方がわからない」「URLとURIの違いが謎」「HTTPを自前で処理するの面倒」…といった問題に直面しがちです。

私も初めてSocketやHttpURLConnectionを触ったとき、エラーと謎の例外の嵐で夜も眠れませんでした。

本記事では、ソケット通信、URL/URI、HTTPリクエスト、タイムアウト設定、IPv6対応まで、小学生にもわかるやさしい言葉とコード例で一気に解説します。

「これを読んでから、REST APIの実装がサクサク進んだ」「ついにIPv6でも動くコードが書けた」と多くの声。

Socketで「Hello」を送り、HttpURLConnectionでJSONをGET、非同期にタイムアウト付きで処理、さらにIPv6で接続してみる…すべてのステップを実例で紹介します。

この記事を最後まで読めば、Javaのネット周りの基礎がしっかり身につき、明日からの開発がグッと楽になります!

ソケット通信の基本――SocketとServerSocketを使ってみよう

ソケット通信は、コンピューター同士が手をつないでデータをやり取りする仕組みです。JavaではSocketとServerSocketクラスを使って簡単に実現できます。

Socketは“クライアント側”が使い、ServerSocketは“サーバー側”が使います。ServerSocketが待ち受けポートを開き、Socketがそこへ接続すると、両者の間でInputStream/OutputStreamを通じて文字やバイトを送受信できるのです。

まずはサーバー側の処理です。

import java.net.ServerSocket;
import java.net.Socket;
import java.io.*;

public class SimpleServer {
  public static void main(String[] args) throws IOException {
    ServerSocket server = new ServerSocket(5000);
    System.out.println("サーバー起動: ポート5000で待機中...");
    Socket client = server.accept();
    BufferedReader in = new BufferedReader(
      new InputStreamReader(client.getInputStream())
    );
    String msg = in.readLine();
    System.out.println("受信メッセージ: " + msg);
    client.close();
    server.close();
  }
}

次にクライアント側です。

import java.net.Socket;
import java.io.*;

public class SimpleClient {
  public static void main(String[] args) throws IOException {
    Socket socket = new Socket("localhost", 5000);
    PrintWriter out = new PrintWriter(
      socket.getOutputStream(), true
    );
    out.println("Hello, Server!");
    socket.close();
  }
}
import java.net.Socket;
import java.io.*;

public class SimpleClient {
  public static void main(String[] args) throws IOException {
    Socket socket = new Socket("localhost", 5000);
    PrintWriter out = new PrintWriter(
      socket.getOutputStream(), true
    );
    out.println("Hello, Server!");
    socket.close();
  }
}

このように、ServerSocket.accept()で接続を待ち、Socket.getInputStream()/getOutputStream()で通信します。

SocketとServerSocketを使えば、Javaでネットワーク通信の雛形がすぐに作れるので、まずは上の例を動かしてみましょう!

URLとURIの違いと使い分けをスパッと理解

URLとURIは似ていますが、URLは“場所を示す住所”、URIは“名前も含む住所または名前全般”と覚えるとわかりやすいです。

URI(Uniform Resource Identifier)はリソースを一意に識別する文字列の総称。URL(Uniform Resource Locator)はURIの一種で、ネット上のリソースへのアクセス方法(例:https://example.com)を示します。つまり、すべてのURLはURIですが、すべてのURIがURLではありません。

import java.net.URI;
import java.net.URL;

// URIを作成(スキームやパスなどリソース識別全般)
URI uri = new URI("urn:isbn:978-4798153146");
System.out.println(uri.getScheme()); // → urn

// URLを作成(アクセス可能な場所)
URL url = new URL("https://example.com/index.html");
System.out.println(url.getProtocol()); // → https
System.out.println(url.getHost());     // → example.com

URN(Uniform Resource Name)もURIの一種ですが、アクセス方法は含まず名前のみを表します。

とにかく「アクセスできるかどうか」を含めて書くのがURL、「何者かを識別する」のがURIと覚えれば、使い分けがグッと楽になります!

HttpURLConnectionでHTTPリクエスト/レスポンス自前処理

Java標準の HttpURLConnection クラスを使えば、外部サーバーへのGET/POSTリクエストを自分で組み立てて送信し、レスポンスを受け取れます。

ライブラリに頼らずに動作原理を理解することは、問題発生時の原因特定に役立ちます。また軽量なコードで、依存を増やさずに済むメリットもあります。

まずは簡単なGETリクエスト例です。

import java.net.*;
import java.io.*;

URL url = new URL("https://jsonplaceholder.typicode.com/todos/1");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(5000);
con.setReadTimeout(5000);

int status = con.getResponseCode();
BufferedReader in = new BufferedReader(
  new InputStreamReader(con.getInputStream())
);
String inputLine;
StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
  content.append(inputLine);
}
in.close();
con.disconnect();
System.out.println("ステータス:" + status);
System.out.println("レスポンス:" + content.toString());

POSTリクエストも同じ流れで、setDoOutput(true)OutputStream へ書き込むだけです。

HttpURLConnection を使えば、細かい設定も自前でできるので、外部API連携の基礎をしっかり押さえたいときに最適です。

タイムアウト設定&非同期通信の基本パターン

ネットワーク通信は相手が遅いとプログラムが止まってしまいます。だからタイムアウトを設定し、必要なら非同期で動かすことが大事です。

例えばサーバーからの応答が長い間帰ってこないと、画面が固まったり他の処理が進まなくなります。setConnectTimeoutsetReadTimeout で接続や読み込みの待ち時間を制御し、非同期なら別スレッドで通信を行えば、メイン処理を止めずにすみます。

まずタイムアウト設定の例です。HTTP通信で5秒以上かかると自動で例外が投げられます。

HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(5000); // 接続待ち最大5秒
con.setReadTimeout(5000);    // 読み込み待ち最大5秒

次に非同期通信の基本パターン。Javaでは ExecutorService を使って別スレッドで実行します。

import java.util.concurrent.*;

ExecutorService exec = Executors.newSingleThreadExecutor();
Future<String> future = exec.submit(() -> {
  HttpURLConnection c = (HttpURLConnection) url.openConnection();
  c.setConnectTimeout(3000);
  c.setReadTimeout(3000);
  try (BufferedReader r = new BufferedReader(
         new InputStreamReader(c.getInputStream()))) {
    return r.readLine();
  }
});

try {
  String result = future.get(4, TimeUnit.SECONDS); // 最大4秒待つ
  System.out.println("結果:" + result);
} catch (TimeoutException te) {
  System.out.println("通信がタイムアウトしました");
  future.cancel(true);
}
exec.shutdown();

これで、メイン処理を止めずに通信し、かつ長引く場合は自動で中断できます。

タイムアウトと非同期を組み合わせれば、ユーザー体験を損なわずに安全なネット通信が実現できます!

IPv6対応とInetAddressでのホスト解決

JavaでIPv6アドレスも扱えると、最新のネットワーク環境でも問題なく動作します。InetAddressクラスを使って、IPv4/IPv6の両方に対応しましょう。

近年はIPv4の枯渇により、IPv6が普及しています。従来のIPv4アドレス(例: 192.168.0.1)のほか、IPv6アドレス(例: 2001:db8::1)でも名前解決や接続が行えるように実装しておくことが重要です。

以下はホスト名からIPアドレスを取得し、IPv6にも対応する例です。

import java.net.*;

public class ResolveHost {
  public static void main(String[] args) throws Exception {
    String host = "example.com";
    InetAddress[] addrs = InetAddress.getAllByName(host);
    for (InetAddress addr : addrs) {
      System.out.println(
        addr instanceof Inet6Address ? "IPv6: " : "IPv4: "
        + addr.getHostAddress()
      );
    }
  }
}

このコードは、対象ホストの全IPアドレスを取得し、IPv4ならInet4Address、IPv6ならInet6Addressとして判別しています。

InetAddress.getAllByName()を使えば、IPv4もIPv6もまとめて解決できます。これで最新のネット環境にも強いJavaアプリが作れます!

まとめ:Javaでネットワークを自由に操る5つの学び

本記事では、Javaでのネットワークプログラミングの基礎から応用までを、小学5年生にもわかるやさしい言葉とコード例で解説しました。

  1. ソケット通信の基本:ServerSocketとSocketでTCP接続を実現し、InputStream/OutputStreamでデータをやり取り
  2. URLとURIの違い:URIはリソースを識別、URLはアクセス方法を含むURIの一種と理解して使い分け
  3. HttpURLConnectionによるHTTP処理:GET/POSTリクエストを自前で構築し、レスポンスを読み込む方法
  4. タイムアウト&非同期通信setConnectTimeout/setReadTimeoutExecutorServiceでプログラムを止めない安全設計
  5. IPv6対応とホスト解決InetAddress.getAllByName()でIPv4/IPv6両対応のDNSルックアップを実現

これらのテクニックを組み合わせることで、Javaで本格的なネットワークアプリケーションが作れます。ぜひ実際のプロジェクトで試し、ネットワーク制御を自由自在に扱えるようになりましょう!

タイトルとURLをコピーしました