next up previous contents
Next: HTTP Up: Network Previous: Server Client model

Client

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

ちなみに、これまでは、ネットワーク・プログラミングを、ソケット・プログラミング とも呼んで来ましたが、こうした呼び方も、これからは変わってゆくのかも知れ ません。

Socket

先のCプログラムと等価のJava プログラムを次に記します。

  Socket s = new Socket("www.wakhok.ac.jp", 80 );

なんと、一行で済んでしまいました。Java の Socketは、Cでのように通信の端点を 表すだけではなく、Socketクラスのインスタンスを作ることが、サーバとの コネクションを確立することになっているのです。

また、ここでは、IPアドレスではなくホスト名だけで、コネクションを 張っています。もちろん、ホスト名を知らなくとも、IPアドレスだけで コネクションを張ることも、コンストラクタを少し変えれば、簡単に出来ます。 次のは、その例です。ここでは、  という、新しいクラスが登場しています。

getInputStream()/getOutputStream()

コネクションを張ることは、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

第一引数はホスト名で、第二引数はファイルの名前です。この時、 ファイル名の先頭に、"/"をつけるのを忘れないで下さい。



maruyama@wakhok.ac.jp