クライアントは、必要に応じてサーバに接続を要求します。 通常、クライアントは、マシンのアドレスと、通信するサーバ・プロセスを特定する ポート番号を指定して、サーバとの間に「コネクション」を張ろうとします。 すなわち、クライアント・サーバ間の恒常的な双方向の通信路を開こうとします。 この通信路の両端の点を、ネットワーク・プログラミングでは、「ソケット」と 呼んでいます。いったん、コネクションが張られれば、あとは、この端点のソケット が、ファイル・ディスクリプタと同じ役割を果たしますので、ソケットに対して、 read/write を行えば、情報が流れることになります。
次の例は、クライアントがサーバに対してコネクションを確立するまでの、Cのコード を示しました。沢山のヘッダ・ファイルがあったり、なかなか複雑です。
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <stdio.h> ConnectToWWW() { struct sockaddr_in name; struct hostent *hp, *gethostbyname(); int www; char works[1024]; www = socket(AF_INET, SOCK_STREAM, 0); if (www < 0) { perror("opening stream socket"); exit(1); } strcpy(works, "www.wakhok.ac.jp"); hp = gethostbyname(works); if (hp == 0) { fprintf(stderr, "%s: unknown host\n", works); exit(2); } bcopy((char *) hp->h_addr, (char *) &name.sin_addr, hp->h_length); name.sin_family = AF_INET; name.sin_port = 80 ; if (connect(www, (struct sockaddr *) & name, sizeof(name)) < 0) { fprintf(stderr, "www connect failed .\n"); fprintf(stderr, "Host=%s,port=%d\n", Host, name.sin_port); exit(1); } sprintf(works, "WWW Server %s accepts connection !!\n", Host); if (debugLevel &= 3) fprintf(stderr, "%s", works); return (www); }
ちなみに、これまでは、ネットワーク・プログラミングを、ソケット・プログラミング とも呼んで来ましたが、こうした呼び方も、これからは変わってゆくのかも知れ ません。
先のCプログラムと等価のJava プログラムを次に記します。
Socket s = new Socket("www.wakhok.ac.jp", 80 );
なんと、一行で済んでしまいました。Java の Socketは、Cでのように通信の端点を 表すだけではなく、Socketクラスのインスタンスを作ることが、サーバとの コネクションを確立することになっているのです。
また、ここでは、IPアドレスではなくホスト名だけで、コネクションを 張っています。もちろん、ホスト名を知らなくとも、IPアドレスだけで コネクションを張ることも、コンストラクタを少し変えれば、簡単に出来ます。 次のは、その例です。ここでは、 という、新しいクラスが登場しています。
コネクションを張ることは、Socketクラスのインスタンスを作るだけで出来ることは 分かりました。それでは、ネットワーク上でのデータの入出力は、どのように行われる のでしょうか?
Socket s = new Socket("www.wakhok.ac.jp", 80 ); DataInputStream in = new DataInputStream( s.getInputStream() ); PrintStream out = new PrintStream( s.getOutputStrream() );
この例が示しているように、ソケット・オブジェクトに対して、メソッド getInputStream() / getOutputStream()を働かせると、そのソケットに対応した 入出力のストリームが得られるのです。
次の例 wclient.java は、WWWサーバに働きかけて、ページの内容を 出力するというものです。 以前にも、URL や、URLConnectionを使った同じようなサンプルを 作ってきたと思いますが、ここでは、Socket クラスと、HTTPというプロトコル が使われています。
import java.net.*; import java.io.*; class wclient { DataInputStream in = null; PrintStream out = null; Socket s = null ; wclient(String host, String file){ try { s = new Socket( host , 80 ); in = new DataInputStream(s.getInputStream()); out = new PrintStream(s.getOutputStream()); String str= null ; out.println("GET " + file + " HTTP/1.0"); out.println(); while((str = in.readLine()) != null){ System.out.println(str); } } catch (Exception e){ System.err.println("Exception(new 3) : "+e); } } public static void main(String argv[]){ try { wclient uc = new wclient(argv[0],argv[1]); } catch (Exception e){ System.err.println("Exception (main) : "+e); } } }
このプログラムは、次のようにして実行します。
java wclient www.wakhok.ac.jp /inside.html
第一引数はホスト名で、第二引数はファイルの名前です。この時、 ファイル名の先頭に、"/"をつけるのを忘れないで下さい。