本ページはプロモーションが含まれています

Java入門

Javaプログラミングで理解するTCP IPとソケット通信

トム

・都内自社開発IT企業勤務/javaのバックエンドエンジニア
/java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎

Javaプログラミングでソケット通信を理解したいあなたに向けて、本記事では「サーバーとクライアントのやり取りはどう実現されているのか」「TCPプロトコルの特徴と役割」「3ウェイ・ハンドシェイクによる接続の確立」までを丁寧に解説します。

SocketとServerSocketの使い方を実際のコードで追体験しながら、ネットワークの基礎が自然と身につく構成になっています。

読み終える頃には、Javaでソケット通信を用いたシンプルなチャットアプリが自力で作れるレベルに到達するでしょう。

双方向通信のしくみを実装しながら、プログラムの流れや接続の裏側までしっかり把握したい方に最適な内容です。

ソケット通信とは?

ソケット通信とは、ネットワーク上の2つのプログラムが、ソケットと呼ばれる通信口を使ってやりとりする仕組みです。

具体的には、以下のような構成になります。

ポイント

  • サーバー:通信を待ち受ける側
  • クライアント:接続してデータを送る側

この2者が1対1でつながることで、データのやり取りができるようになります。

ソケットとは?

「ソケット」とは、通信を行うための“窓口”のようなものです。

送る側(クライアント)と受け取る側(サーバー)が、ソケットという窓口を通じてデータをやり取りします。

javaでは、クライアントはSocketクラスを使って接続し、サーバーはServerSocketクラスを使って接続を待ち受けます。

ソケット通信はどうやって実現してるの?

Javaのソケット通信は、裏側でTCP(Transmission Control Protocol)という通信プロトコルを使っています。

TCPは、以下のような特徴を持っています。

  • データが順番通りに届く
  • 途中でデータが欠けたり壊れたりしないよう保証する
  • 通信の開始・終了を丁寧に行う(3ウェイ・ハンドシェイク)

つまり、「ちゃんと確実にデータを届けてくれる郵便屋さん」みたいなものです。

JavaでSocketやServerSocketを使った通信は、基本的にこのTCP通信の仕組みにのっとって動いています

だから、ネットワークの知識があまりなくても、Javaのソケット通信を使えば自然と「正しく届く通信」が実現できるのです。

3ウェイ・ハンドシェイク

3ウェイ・ハンドシェイクについて詳しく見てきましょう。

手順1:クライアント → サーバーへ「SYN」(接続要求)

クライアントが「これから通信したいよ!」とサーバーにリクエストを送ります。

このとき送られるのが「SYN(シンクロナイズ)」という信号。

手順2:サーバー → クライアントへ「SYN-ACK」(許可と応答)

サーバーはそれを受け取って、「いいよ、準備できてるよ」と返事します。

これが「SYN-ACK(シンクロナイズ+応答)」。

手順3:クライアント → サーバーへ「ACK」(最終確認)

クライアントは、サーバーからの返事を確認して「じゃあ始めますね!」と返します。

これが「ACK(確認応答)」です。

sequenceDiagram participant クライアント participant サーバー クライアント->>サーバー: SYN(接続要求) サーバー-->>クライアント: SYN-ACK(接続許可+応答) クライアント->>サーバー: ACK(応答) Note right of サーバー: 接続確立(通信開始)

Javaでソケット通信を実装してみよう

実際にコードを書いてみるとイメージが掴みやすくなります。ここでは、サーバーとクライアントを別々のJavaクラスとして実装します。

Javaのサーバー側のコード

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

public class SimpleServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(12345);
        System.out.println("サーバーがポート12345で待機中...");

        Socket clientSocket = serverSocket.accept();
        System.out.println("クライアントが接続しました。");

        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);

        String inputLine;
        while ((inputLine = in.readLine()) != null) {
            System.out.println("受信: " + inputLine);
            out.println("サーバーからの応答: " + inputLine);
        }

        in.close();
        out.close();
        clientSocket.close();
        serverSocket.close();
    }
}

コードのポイント解説

ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("サーバーがポート12345で待機中...");

ポイント

  • ServerSocket:サーバー側の待ち受け口。
  • 12345:通信に使うポート番号(自由に選べるが、重複に注意)。
  • serverSocket.accept():クライアントからの接続を待つ(ブロッキグ処理)。
Socket clientSocket = serverSocket.accept();
System.out.println("クライアントが接続しました。");

ポイント

  • クライアントからの接続を待つ
  • クライアントからの接続を受け入れ、双方向通信用の Socket オブジェクトを取得。
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);

ポイント

  • BufferedReader:クライアントから送られてくるテキストを1行ずつ読むための準備。
  • PrintWriter:クライアントへテキストを送るための出力。
String inputLine;
while ((inputLine = in.readLine()) != null) {
    System.out.println("受信: " + inputLine);
    out.println("サーバーからの応答: " + inputLine);
}

ポイント

  • クライアントからのメッセージを1行ずつ読み込む。
  • 読み込んだ内容を System.out.println() で表示。
  • クライアントへ「サーバーからの応答:」を付けて返信。
  • null が返ると(=クライアント切断)、ループ終了。

Javaのクライアント側のコード

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

public class SimpleClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost", 12345);
        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

        String userInput;
        System.out.println("メッセージを入力してください:");
        while ((userInput = stdIn.readLine()) != null) {
            out.println(userInput);
            System.out.println("サーバーから: " + in.readLine());
        }

        in.close();
        out.close();
        stdIn.close();
        socket.close();
    }
}

コードのポイント解説

Socket socket = new Socket("localhost", 12345);

ポイント

  • localhost: 自分のPC(ループバックアドレス)。
  • 12345: サーバーが待ち受けているポート。
  • new Socket(...) で TCP 接続を開始。
    • サーバーが動いていないと ConnectException が発生。
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

ポイント

名前用途
stdInユーザーからの標準入力取得(キーボード入力)
inサーバーからのメッセージを受信
outサーバーへのメッセージ送信(true で自動フラッシュ)
System.out.println("メッセージを入力してください:");
while ((userInput = stdIn.readLine()) != null) {
    out.println(userInput);
    System.out.println("サーバーから: " + in.readLine());
}

ポイント

  • ユーザーが1行入力するたびに:
    • サーバーへ送信(out.println()
    • サーバーからの返信を受け取り(in.readLine())、表示
in.close();
out.close();
stdIn.close();
socket.close();

ポイント

  • 入出力ストリームとソケットを明示的に閉じてリソースを解放。
  • 必ず close() を行うのは、接続リーク防止の基本。

ソケット通信のポイント

実装してみると、以下の点が重要であることが分かります。

ポイント

  • ServerSocketはクライアントからの接続を受け入れる役割
  • Socketは接続を行い、InputStream/OutputStreamを使って通信する
  • 通信は一方通行ではなく、双方向(送る・受け取る)が可能
  • 必ず入出力ストリームを閉じて、リソースを開放すること

ソケットの流れは以下の通りになります。

[ユーザー入力] → [SimpleClient] →→→ [SimpleServer]
(クライアントが入力 → サーバーへ送信 → サーバーが応答 → クライアントが表示)

まとめ:Javaでソケット通信は難しくない

本記事では、Javaにおけるソケット通信の基本から、実際のコードを用いたサーバー・クライアント間のデータ送受信の実装までを体系的に解説しました。

TCPプロトコルの仕組みや3ウェイ・ハンドシェイクの流れ、JavaのSocket・ServerSocketクラスの使い方を一貫して学ぶことで、ネットワーク通信の基礎が自然に身につきます。

【要点まとめ】

  • ソケット通信とはネットワーク越しにプログラム同士が通信する仕組み
  • サーバーはServerSocketで待ち受け、クライアントはSocketで接続する
  • Javaのソケット通信はTCPプロトコルを利用している
  • TCPは順序通り・確実にデータを届ける特徴がある
  • 接続開始時は3ウェイ・ハンドシェイクが行われる
  • サーバー側はaccept()でクライアントの接続を待つ
  • クライアント側はユーザー入力を送信し、サーバーからの応答を受信する
  • 通信は双方向であり、入力と出力のストリームをそれぞれ使う
  • 通信終了時はすべてのリソースを明示的にcloseすることが重要
  • サンプルコードを理解することで自作アプリ開発の基礎が築ける

Javaでのソケット通信は、一見とっつきにくく感じるかもしれませんが、仕組みさえ理解してしまえば非常にシンプルです。

サンプルコードを実行しながら、通信の流れを体感することで、ネットワークプログラミングの土台がしっかりと身につきます。

  • この記事を書いた人
  • 最新記事

トム

・都内自社開発IT企業勤務/javaのバックエンドエンジニア
/java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎

-Java入門