作成日: 2003/03/05

Java で簡単ソケットプログラミング

概要

必要があって java でのソケットプログラミングについて調べたのですが、C で書くのと比べると ものすごく簡単にプログラミングできてしまいます。おまけに java はクラスライブラリが充実しているので、 取得したバイト列の扱いもものすごく楽に行えます。もう、C ではめんどうくさくてプログラミングできないかもしれないと 思ってしまったくらいです。
コード量が少ないので、ソースを読んでもらった方が早いのですが、簡単に説明させていただきます。 なお、以下の説明は Java 2 SDK, Standard Edition version 1.4.0(以下 JDK 1.4) の環境で行っています。

ソケットプログラミングに必要なクラス

サーバ側ソケットは java.net.ServerSocket を使います。コンストラクタの形式は色々とあるようですが、 以下ではポート番号のみを指定するコンストラクタを使用しています。
また、クライアント側ソケット、および、サーバ側でクライアントと接続されたソケットを扱うには java.net.Socket を使います。 これまた、コンストラクタの形式が色々ありますが、以下では引数なしのコンストラクタを使っています。

サーバ側プログラミング

bind() も listen() も必要ありません。コンストラクタにポート番号を与えてインスタンスを作成した後 accept() するだけです。 もし accept() にタイムアウトを設定したいのなら setSoTimeout() を使ってタイムアウト値をミリ秒単位で指定して accept() する前に呼び出しておけば、指定した時間が経過すると java.net.SocketTimeoutException がスローされます。 例えば、以下のようになります。

    int port; // ポート番号
    int timeout_msec = 10000; // accept() のタイムアウトは10秒にしてみる。

    port = 50000; // 例えばポート番号は 50000 番にする。

    // サーバソケットの作成
    ServerSocket svsock = new ServerSocket(port);
    svsock.setSoTimeout(timeout_msec);  // ※必要があるときのみ設定する。

    // クライアントからの接続を受け付ける。
    // ※クライアントからの接続がくるまでここでブロックする。
    try {
        Socket sock = svsock.accept();

        // クライアントと接続されたソケットを利用して処理を行う。
        ...
    } catch (SocketTimeoutException e) {
        // accept() タイムアウト時の処理をする。
        ...
    }
クライアント側プログラミング

インスタンスを作成した後、接続したいサーバのホスト名とポート番号を指定して connect() を呼ぶだけです。 例えば、以下のようになります。
※ちなみに、以下で使用している形式の connect() メソッドおよび InetSocketAddress クラスは JDK 1.4 から導入されました。

    // 例えば、ホスト javasv、ポート番号 50000 番に接続する。
    String host = "javasv";
    int port = 50000;

    try {
        // ソケットを作成してサーバに接続する。
        Socket sock = new Socket();
        sock.connect(new InetSocketAddress(host, port));

        // サーバと接続されたソケットを利用して処理を行う。
        ...
    } catch (Exceptoin e) {
        ...
    }
ソケットへの入出力

取得したソケットへの入出力はメソッド getInputStream() で入力用ストリームを、getOutputStream() で出力用ストリームを 手に入れ、それを使って行います。通常は、InputStream および OutputStream のインスタンスをそのまま使わず、 便利なクラスに接続して使います。例えば以下のようになります。
※以下では、ソケットから取得した OutputStream を扱いやすいように DataOutputStream に接続して使っています。

    try {
        sock = ...;  // ソケットを手に入れる。

        // ソケットに出力する。
        DataOutputStream out = new DataOutputStream(sock.getOutputStream());
        out.writeBytes("Hello!\n");

        ...
    } catch (Exception e) {
        ...
    }
ソケットの後始末

ソケットがいらなくなったら close() するだけです。ソケットに関連したリソースが解放されます。 例えば、以下のようになります。

    try {
        sock = ...;  // ソケットを手に入れる。

        // いろいろな処理をする。
        ...

        // 後始末する。
        sock.close();
    } catch (Exception e) {
        ...
    }
その他

すみません。説明するほどもなかったですね。でも、それだけコードを書く必要がなく簡単ということだと思います。 これだけ、簡単にソケットプログラミングができるというのは、私にはものすごいメリットだと感じました。
手元にある JDK のドキュメントの Socket クラスを眺めてみると随分とたくさんのメソッドがあるのがわかります。 ソケットオプションなども豊富に用意されているようです。興味がある方は、ぜひ一度 JDK のドキュメントに目を通してみてください。

サンプルソース
Sv.java (1.61 KB)
サーバプログラムです。クライアントからの接続に対し、"Hello!" の文字列と改行を返します。 ちなみにクライアントと接続後の処理は、スレッド化してあります(あんまり意味ありませんが・・)。
Cl.java (1.30 KB)
クライアントプログラムです。サーバに接続して文字列を受け取ります。

なお、コンパイルには JDK 1.4 以上が必要になります。JDK は Sun のサイトなどから手にいれてください。 雑誌の付録などにもついています。今の JDK はインストールしたらすぐ使えます。 特別な必要がない限り、昔のようにクラスパスを設定する必要はありません。
上記ソースのコンパイルは JDK が導入された環境で、以下のように行います。
※C:\Work 下に Sv.java、Cl.java が格納されているものとします。

C:\Work>javac Sv.java                                  ・・・サーバをコンパイル
C:\Work>javac Cl.java                                  ・・・クライアントをコンパイル

プログラムを動作させるときは、サーバを先に起動します。例えば以下のようにします。
※以下ではサーバを 50000 番ポートで待つようにしています。

C:\Work>java Sv 50000

次にクライアントを上記で起動したサーバに接続して文字列を得ます。

C:\Work>java Cl localhost 50000
Hello!


C:\Work>