システムプログラム(第6回): echoサービスのクライアント(Java版)

                                       筑波大学 システム情報系 情報工学域
                                       新城 靖
                                       <yas@cs.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~syspro/2018/2018-05-23 /echo-client-java.html
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~syspro/2018/
http://www.coins.tsukuba.ac.jp/~yas/

echoサービスのクライアント(Java版)

Java 言語で記述した echo-client-fdopen-one.c である。
   1:	
   2:	/*
   3:	  EchoClientOne.java -- 文字列を送受信するクライアント(TCP/IP版)
   4:	  ~yas/syspro/ipc/EchoClientOne.java
   5:	  Created on 2004/02/14 21:09:17
   6:	*/
   7:	
   8:	import java.net.*;
   9:	import java.io.*;
  10:	
  11:	class EchoClientOne
  12:	{
  13:	        public static void main(String argv[]) throws IOException {
  14:	                if( argv.length != 3 )
  15:	                {
  16:	                        System.err.println("Usage: % java EchoClientOne host port 'message'");
  17:	                        System.exit( -1 );
  18:	                }
  19:	                String server = argv[0];
  20:	                int portno = Integer.parseInt( argv[1] );
  21:	                String message = argv[2];
  22:	                echo_client_one( server, portno, message );
  23:	        }
  24:	
  25:	        public static void echo_client_one( String server, int portno, 
  26:	                                            String message )
  27:	                throws IOException
  28:	        {
  29:	                Socket sock = new Socket( server, portno );
  30:	                InputStream in = sock.getInputStream();
  31:	                OutputStream out = sock.getOutputStream();
  32:	
  33:	                echo_send_request( out, message );
  34:	                stdout.printf("sent: %d bytes [%s\n]\n", message.length()+1,message );
  35:	                String rline = echo_receive_reply( in );
  36:	                stdout.printf("received: %d bytes [%s]\n",rline.length(), rline);
  37:	                in.close();
  38:	                out.close();
  39:	                sock.close();
  40:	        }
  41:	        public static void echo_send_request( OutputStream out, String message )
  42:	                throws IOException
  43:	        {
  44:	                printfOS( out, "%s\n", message );
  45:	        }
  46:	        public static String echo_receive_reply( InputStream in )
  47:	                throws java.io.IOException
  48:	        {
  49:	                String rline = readLineIS( in );
  50:	                return( rline );
  51:	        }
  52:	
  53:	        public static int printfOS( OutputStream out, String format, Object ... args )
  54:	                throws IOException
  55:	        {
  56:	                String s = String.format( format, args );
  57:	                return( putStringOS( out, s ) );
  58:	        }
  59:	        public static int putStringOS( OutputStream out, String message )
  60:	                throws IOException
  61:	        {
  62:	                byte b[] = message.getBytes();
  63:	                out.write( b );
  64:	                out.flush();
  65:	                return( b.length );
  66:	        }
  67:	        final static int ReadLineISMaxLine = 1024;
  68:	        public static String readLineIS( InputStream is ) throws IOException
  69:	        {
  70:	                byte line[] = new byte[ReadLineISMaxLine];
  71:	                int c, len = 0 ;
  72:	                while( (c=is.read()) != -1 )
  73:	                {
  74:	                        line[len++] = (byte) c;
  75:	                        if( len == line.length || c== '\n' )
  76:	                                break;
  77:	                }
  78:	                if( len == 0 )
  79:	                        return null;
  80:	                String s = new String( line,0,len );
  81:	                return( s );
  82:	        }
  83:	
  84:	        static java.io.BufferedReader stdin = 
  85:	                new java.io.BufferedReader( new java.io.InputStreamReader(System.in) );
  86:	        static java.io.PrintStream stdout = System.out;
  87:	        static java.io.PrintStream stderr = System.err; 
  88:	}
このプログラムの基本的な部分は、 echo-client-fdopen-one.c と同じである。 以下に、Java のメソッド名と C の関数名の対応を示す。
Java C
new Socket tcp_connect()
sock.getInputStream(), sock.getOutputStream() fdopen_sock()
printfOS() fprintf()
readLineIS() fgets()
readLineIS() は、Java でよく使われる BufferedReader の readLine() とは 異なり、行末の改行 \n を削除しない。

実行例

以下に実行例を示す。
$ cp ~yas/syspro/ipc/EchoClientOne.java . [←]
$ javac EchoClientOne.java [←]
$ java EchoClientOne [←]
Usage: % java EchoClientOne host port 'message'
$ java EchoClientOne crocus10.coins.tsukuba.ac.jp 7 hello [←]
sent: 6 bytes [hello
]
received: 6 bytes [hello
]
$ java EchoClientOne crocus10.coins.tsukuba.ac.jp 7 exit [←]
sent: 5 bytes [exit
]
received: 5 bytes [exit
]
$ java EchoClientOne crocus10.coins.tsukuba.ac.jp 7 quit [←]
sent: 5 bytes [quit
]
received: 5 bytes [quit
]
$ []

Java BufferedReader のブァッファリング

Java でよく使われる BufferedReader は、その名が示すように内部にバッファ を持つ。BufferedReader を利用した場合、元のソケットの InputStream の read(byte[]) 等でバイト単位で読み込むと、不整合が生じる。 BufferedReader の内部のバッファに溜まっているデータが欠落することになる。

上記の readLineIS() は、バッファリングをしていないので、そのような問題 はない。InputStream のread(byte[]) 等のバイト単位での読み込みと混在させ ることができる。HTTP クライアントでバイナリのデータを扱いたい時にも、 readLineIS() では問題がない。


Last updated: 2018/05/21 14:36:45
Yasushi Shinjo / <yas@cs.tsukuba.ac.jp>