ソケット通信の基本

docs

今回は、いよいよJavaプログラミングの醍醐味の一つ、ネットワークプログラミングの世界に足を踏み入れてみましょう。特に、ネットワークプログラミングの基本中の基本であるソケット通信について、初心者の方でも理解できるようにわかりやすく解説していきます。

ネットワークプログラミングって何?

ネットワークプログラミングと聞くと、「難しそう」「専門知識が必要そう」と感じるかもしれませんね。でも安心してください。簡単に言うと、インターネットを通じてコンピュータ同士が会話するためのプログラムを作ることです。私たちが普段使っているWebブラウザやチャットアプリも、裏側ではネットワークプログラミングが動いています。

ソケットって何?

「ソケット」と聞くと、家電製品のコンセントをイメージする人もいるかもしれませんね。ネットワークの世界でのソケットも、それに似ています。

コンピュータがネットワーク上で他のコンピュータと通信するには、まるで電話をかけるように、どこかの「窓口」を通じてやり取りします。この「窓口」こそがソケット (Socket) なんです。

ソケットは、例えるなら電話機です。電話機を通じて、相手と会話しますよね。ソケットも同じように、データという「会話」をするためのインターフェースを提供してくれます。

ソケット通信の仕組み

ソケット通信には、大きく分けて2つの役割があります。

  1. サーバー (Server): サービスを提供する側。電話でいうと、電話がかかってくるのを待っている側です。
  2. クライアント (Client): サービスを利用する側。電話でいうと、電話をかける側です。

この2つがそれぞれのソケットを通じて、データの送受信を行います。

サーバー側のソケット

サーバー側は、クライアントからの接続を「待ち受ける」必要があります。これにはServerSocketというクラスを使います。

Java

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

public class SimpleServer {
    public static void main(String[] args) {
        int port = 12345; // 任意のポート番号

        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("サーバーがポート " + port + " で起動しました。");

            // クライアントからの接続を待機
            Socket clientSocket = serverSocket.accept();
            System.out.println("クライアントが接続しました: " + clientSocket.getInetAddress().getHostAddress());

            // ここでクライアントとのデータ送受信の処理を行う

        } catch (IOException e) {
            System.err.println("サーバーエラー: " + e.getMessage());
        }
    }
}

このコードでは、ServerSocketを特定のポート番号(ここでは12345)で作成しています。ポート番号は、コンピュータ上でプログラムを識別するための番号だと思ってください。Webサイトのアドレスの最後に:80とか:443とか付いているのを見たことがあるかもしれません。あれがポート番号です。

serverSocket.accept()は、クライアントからの接続要求が来るまでプログラムの実行を停止(ブロック)します。接続があれば、そのクライアントとの通信に使うSocketオブジェクトを返します。

クライアント側のソケット

クライアント側は、サーバーに接続するためにSocketクラスを使います。

Java

import java.net.Socket;
import java.io.IOException;

public class SimpleClient {
    public static void main(String[] args) {
        String serverAddress = "localhost"; // サーバーのアドレス (今回は自分のPC)
        int port = 12345; // サーバーが待ち受けているポート番号

        try (Socket socket = new Socket(serverAddress, port)) {
            System.out.println("サーバーに接続しました: " + serverAddress + ":" + port);

            // ここでサーバーとのデータ送受信の処理を行う

        } catch (IOException e) {
            System.err.println("クライアントエラー: " + e.getMessage());
        }
    }
}

クライアントは、サーバーのアドレス(ここではlocalhost、つまり自分のコンピュータ)とポート番号を指定してSocketオブジェクトを作成します。これにより、サーバーへの接続が試みられます。

データの送受信

ソケットが確立できたら、いよいよデータの送受信です。データの送受信には、入出力ストリームを使います。JavaのI/O(Input/Output)については、前回の記事で触れた通りです。

文字列の送受信例

ここでは、サーバーがクライアントからメッセージを受け取り、そのメッセージに応答する例を見てみましょう。

サーバー側 (SimpleServer.java)

Java

import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class SimpleServer {
    public static void main(String[] args) {
        int port = 12345;

        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("サーバーがポート " + port + " で起動しました。");

            while (true) { // 複数のクライアントに対応するためにループ
                Socket clientSocket = serverSocket.accept();
                System.out.println("クライアントが接続しました: " + clientSocket.getInetAddress().getHostAddress());

                // クライアントとの通信を別スレッドで行うのが一般的ですが、今回は単純化
                try (
                    BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); // autoFlushをtrueに
                ) {
                    String clientMessage;
                    while ((clientMessage = in.readLine()) != null) {
                        System.out.println("クライアントからのメッセージ: " + clientMessage);
                        out.println("サーバーからの返信: " + clientMessage + " を受け取りました!"); // クライアントに返信
                        if (clientMessage.equalsIgnoreCase("bye")) {
                            break; // "bye"と入力されたら通信終了
                        }
                    }
                    System.out.println("クライアントとの接続を閉じます: " + clientSocket.getInetAddress().getHostAddress());
                } catch (IOException e) {
                    System.err.println("クライアントとの通信エラー: " + e.getMessage());
                } finally {
                    clientSocket.close(); // クライアントソケットを閉じる
                }
            }
        } catch (IOException e) {
            System.err.println("サーバーエラー: " + e.getMessage());
        }
    }
}

クライアント側 (SimpleClient.java)

Java

import java.net.Socket;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Scanner;

public class SimpleClient {
    public static void main(String[] args) {
        String serverAddress = "localhost";
        int port = 12345;

        try (
            Socket socket = new Socket(serverAddress, port);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true); // autoFlushをtrueに
            Scanner scanner = new Scanner(System.in) // 標準入力から読み込む
        ) {
            System.out.println("サーバーに接続しました: " + serverAddress + ":" + port);

            String userInput;
            while (true) {
                System.out.print("メッセージを入力してください (終了する場合は 'bye'): ");
                userInput = scanner.nextLine();
                out.println(userInput); // サーバーに送信

                String serverResponse = in.readLine(); // サーバーからの返信を受け取る
                System.out.println("サーバーからの返信: " + serverResponse);

                if (userInput.equalsIgnoreCase("bye")) {
                    break;
                }
            }
        } catch (IOException e) {
            System.err.println("クライアントエラー: " + e.getMessage());
        }
    }
}

実行してみよう!

  1. まず、SimpleServer.javaをコンパイルして実行します。サーバーが起動して、クライアントからの接続を待ち受ける状態になります。
  2. 次に、別のターミナルを開き、SimpleClient.javaをコンパイルして実行します。クライアントがサーバーに接続し、メッセージのやり取りができるようになります。
  3. クライアント側で何かメッセージを入力してEnterキーを押すと、サーバーに送られ、サーバーから返信が来るのが確認できるはずです。「bye」と入力すると、クライアント側の通信が終了します。

まとめ

今回は、Javaでのネットワークプログラミングの基礎となるソケット通信について学びました。

  • ソケットは、コンピュータがネットワーク上で他のコンピュータと通信するための「窓口」のようなものです。
  • サーバーServerSocketを使って接続を待ち受け、クライアントSocketを使ってサーバーに接続します。
  • データの送受信には、入出力ストリーム(InputStreamOutputStream)を使います。

これで、Javaでシンプルなネットワークアプリケーションを作成する第一歩を踏み出せましたね!次回は、このソケット通信を応用したさらに面白いテーマに挑戦してみましょう。


Javaプログラミングの学習、引き続き頑張ってくださいね!

これまでの記事はこちらから読めますよ!: ToolDocs | 様々なツールや技術情報を紹介します

コメント

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