24. Socket を使った通信

TCP を使った通信プログラムについて説明します(クライアント/サーバ、TCP/IPについての説明は省略)。

(1) TCP

 Java ではネットワークを介した通信プログラムも作ることができます。ネットワークに関連したクラスは java.net パッケージにあります。今回は TCP を使った通信プログラムを作ってみます。

 TCP とは通信規約(通信プロトコル)の1つでインターネットで使われているものです。Windows でもインターネットの設定をするときにみることがあります。

 TCP は電話のような通信方法です。電話は相手に電話をかけて相手が電話に出てくれたら話すことができます。TCP は1度相手(サーバ)に接続して、接続できたらデータのやりとりをはじめます。

 電話をかけるには電話番号が必要なように、コンピュータで通信をするときは相手のホスト名(IPアドレス)とポート番号を知っている必要があります。

(2) サーバ側のプログラム

 TCP を使った通信プログラムではサーバとクライアントでプログラムの作り方が違います。まずはじめにサーバのプログラムを作ってみます。

 サーバーはクライアントからの接続要求を待つ必要があります。これを ServerSocket というクラスで行います。ServerSocket クラスには3種類のコンストラクタがありますが、ここではポート番号のみを指定するものを使ってみます。
ServerSocket(int port) throws IOException

 port 番号は 0 から 65535 までの好きな値を使うことができますが、1024 以下の番号はあらかじめ決められたサービス( FTP や HTTP など)が使っている場合があるので、自分のプログラムでは 1024 より大きいポート番号を使うようにします。

 この ServerSocket で実際にクライアントからの接続要求を待つには accept( ) というメソッドを実行しておきます。

Socket accept( ) throws IOException

 accept( ) メソッドはクライアントから接続があるまで、実行を先に進めません。クライアントが接続すると、Socket クラスのオブジェクトを返して実行を進めます。Socket とはコンピュータ間の通信路をつなぐコンセントのようなものだと思ってください。

 Socket が獲得できたら、この Socket からストリームのオブジェクトを取り出します。

InputStream getInputStream( ) throws IOException
OutputStream getOutputStream( ) throws IOException

 InputStream を獲得して read( ) メソッドを実行すればクライアントからのデータを受信できます。OutputStream を獲得して write( ) メソッドを実行すればクライアントにデータを送信することができます。

  Server.java

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

class Server {
    public static void main(String args[]) {
        System.out.println("Ready!");
        try {
            ServerSocket ss = new ServerSocket(5000);
            while (true) {
                Socket socket = ss.accept();
                InputStream is = socket.getInputStream();
                OutputStream os = socket.getOutputStream();
                DataInputStream dis = new DataInputStream(is);
                DataOutputStream dos = new DataOutputStream(os);
                int recv = dis.readInt();
                System.out.println("受信したデータ : "+recv);
                int send = recv * 10;
                dos.writeInt(send);
                dis.close();
                dos.close();
                is.close();
                os.close();
            }
        } catch (Exception e) {
            System.out.println("Server : IOError");
            e.printStackTrace();
        }
    }
}     


(3) クライアント側のプログラム

 クライアント側のプログラムはサーバのプログラムから ServerSocket の部分を取り除いたようなものです。クライアントがサーバに接続するにはホスト名とポート番号を指定して Socket を作ります。Socket クラスのコンストラクタのうち、ホスト名とポート番号を指定するものは次のような形式です。

 Socket(String hostName,int port) throws UnknownHostException, IOException

 これで Socket を作ることができれば、あとはサーバと同じで、getInputStream( )、getOutputStream( ) でストリームを獲得し、サーバとの通信をします。

  Client.java

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

class Client {
    public static void main(String args[]) {
        if (args.length!=2) {
            System.out.println("使用法:java Client ホスト名 数値");
            System.exit(0);
        }
        try {
            Socket socket = new Socket(args[0],5000);
            InputStream is = socket.getInputStream();
            OutputStream os = socket.getOutputStream();
            DataInputStream dis = new DataInputStream(is);
            DataOutputStream dos = new DataOutputStream(os);
            int send = Integer.parseInt(args[1]);
            dos.writeInt(send);
            int recv = dis.readInt();
            System.out.println("受信したデータ : "+recv);
            dis.close();
            dos.close();
            is.close();
            os.close();
        } catch (Exception e) {
            System.out.println("Client : Error");
            e.printStackTrace();
        }
    }
}

(4) 実行

 まず、MS-DOS プロンプトを2つ立ち上げておいてください。1つはサーバ用、1つはクライアント用に使います。

 はじめにサーバのプログラムを実行します。

C:\java_test>java Server
Ready!

 つぎにもう1つ立ち上げた MS-DOS プロンプトでクライアントのプログラムを実行します。パラメータの1つ目にはホスト名を指定します。今回は自分のコンピュータを指定するので 127.0.0.1 を指定してください。2つ目のパラメータには数値を指定します。

C:\java_test>java Client 127.0.0.1 100

 実行結果は以下のようになります。


 サーバ側の結果

C:\java_test>java Server
Ready!
受信したデータ : 100


 クライアント側の結果


C:\java_test>java Client 127.0.0.1 100
受信したデータ : 1000
前の章(23.synchronized修飾子)   次の章(25.DatagramSocket)