メッセージを加工して送り返すサーバー

受け取るのも送るのも

今回はメッセージを受けとったあと,返事をするサーバーを作ってみます。受信,送信を両方するというところがポイントです。

クライアントも送信した後受信をするように作らなければなりません。

返事をするサーバー

このサーバーも 10001 ポートで待ちます。

プログラム名 Server03.java

/** 受信後返事をするサーバー */
import java.net.*;
import java.io.*;
public class Server03 {
    public static void main( String[] args ) {
        int PORT = 10001;
        String henji = "こちらはサーバーのhogeです。"; //各自変更
        try {
            ServerSocket mysvsoc = new ServerSocket( PORT );
            while( true ) {
               //クライアントが接続してくるまで待ち続ける
                System.out.println( "Server03 waiting..." );
                Socket mysoc = mysvsoc.accept();
               //接続してきたホストの名前を表示
                String remotehost = mysoc.getInetAddress().getHostName();
                System.out.println(remotehost + " からメッセージです。:");
               // メッセージを受信
                InputStreamReader in
                    = new InputStreamReader(mysoc.getInputStream());
                BufferedReader inb = new BufferedReader(in);
               // 今回は1行のみ受信
                String line;
                line = inb.readLine();
                System.out.println( line );
               // メッセージに返信

                OutputStreamWriter out
                  = new OutputStreamWriter(mysoc.getOutputStream());
                BufferedWriter outb = new BufferedWriter(out);
                outb.write( henji );
                outb.newLine();

                outb.close();
                out.close();
                inb.close();
                in.close();
                mysoc.close();
            }
        }
        catch( IOException e ) {
            System.err.println("IO Error");
        }
    }
}

実行すると次のようになって接続を待ちます

$ java Server03
Server03 waiting...

まだサーバーしかなく接続してくるクライアントはありませんのでいつまでもこのままです。しかし,接続があると次のように相手のホスト名とメッセージを表示し,「こちらはサーバーのhogeです。」と返信をして、また待機状態に戻ります。

$ java Server03
Server03 waiting...
vineXX からメッセージです。:
Konnichihwa
Server03 waiting...

サーバーを停止するには ctrl+c (コントロールキーを押しながらc)で止めます。

これはしばらく止めずにおいて,端末(コンソール)を起動してクライアントを作りましょう。もう一度[アプリケーション]-[プログラミング]-[java]を選ぶのが一番簡単です。

クライアントプログラム

今度もポート 10001 を使います。サーバーと逆で、送信した後に受信するように作ります。

プログラム名 Client03.java

/** 送信後受信するクライアント */
import java.io.*;
import java.net.*;
public class Client03 {
    public static void main( String[] args ) {
        /* 通信に使用するポート番号 */
        int PORT = 10001;
        try {
            Socket mysoc = new Socket( args[0], PORT );
            OutputStreamWriter out
                  = new OutputStreamWriter(mysoc.getOutputStream());
            BufferedWriter outb = new BufferedWriter(out);
            //System.out.println( args[0]+" にメッセージを送ります。" );

            outb.write( args[1] );
            outb.newLine();
            outb.flush();

            InputStreamReader in 
                  = new InputStreamReader(mysoc.getInputStream());
            BufferedReader inb = new BufferedReader(in);
            String line;
            line = inb.readLine();
            System.out.println( line + "<-" );

            inb.close();
            in.close();
            outb.close();
            out.close();
            mysoc.close();
        }
        catch( UnknownHostException e ) {
            System.err.println( "Host not found" );
        }
        catch( IOException e ) {
            System.err.println("IO Error");
        }
    }
}

ここで大事なのが、outb.flush(); です。BufferedWriter はバッファにデータをためていっぱいなったり、クローズされる時にまとめて送信しようとします。もちろんその方が仕事の効率はいいのですが、今回のような例ではバッファに書き込まれるが実際には送信されないということが起こります。これを今までにたまっている分を送信させるメソッドが outb.flush(); なのです。

前回のプログラムでは、送信後すぐにクローズされたのでこの問題は起こりませんでした。

実行する時には、

$ java Client03 vineXX Konnichihwa.

というように引数として通信したいホストの名前と、通信内容を引数として入れます。まずは自分の使っているコンピュータのホスト名でテストしましょう。

実行すると次のようにサーバーの返答があります。

$ java Client03 vineXX Konnichihwa.
こちらはサーバーのhogeです。<-
$

課題

クライアントの送ってきた文字列を [ ] で囲んで返すように変えてみましょう。

プログラム名 Server031.java

クライアントは同じものが使えます。

もくじ

Javaプログラミング
聖愛中学高等学校
http://www.seiai.ed.jp/
Dec.2008
Nov.2012