クライアントは、必要に応じてサーバに接続を要求します。 通常、クライアントは、マシンのアドレスと、通信するサーバ・プロセスを特定する ポート番号を指定して、サーバとの間に「コネクション」を張ろうとします。 すなわち、クライアント・サーバ間の恒常的な双方向の通信路を開こうとします。 この通信路の両端の点を、ネットワーク・プログラミングでは、「ソケット」と 呼んでいます。いったん、コネクションが張られれば、あとは、この端点のソケット が、ファイル・ディスクリプタと同じ役割を果たしますので、ソケットに対して、 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
第一引数はホスト名で、第二引数はファイルの名前です。この時、 ファイル名の先頭に、"/"をつけるのを忘れないで下さい。