-title: ネットワークプログラミング --目的 この実験では、ネットワークプログラミングを詳細に学ぶ。インターネットで 使われている通信規約であるTCP/IPや、Ethernet の構造、リピータやルータ などに関する知識を実際のコンピュータ上で試す。さまざまなネットワーク管 理のためのコマンドについても勉強する。Mailサーバ、NNTPサーバやWWWのサー バなどのプロトコルを調べる。そして、C言語とJavaによりクライアントのプ ログラムを作成、および、サーバのプログラムを作成する。さらにモーバイル・ エージェントに関してもプログラムを行う。 情101 ソフトウエア基礎 I 2 情102 ソフトウエア基礎 II 2 情103 ソフトウエア基礎演習 I 1 情104 ソフトウエア基礎演習 II 1 情211 情報通信 2 --課題の選択 以下の 課題 は必修とする。 ■課題 サービス ■課題 IPアドレスとイサーネットアドレス (必修) ■課題 ARP (必修) ■課題 ブロードキャスト ■課題 ルータ ■課題 telnet を使った finger サーバへのアクセス 以下の課題は3つのグループのうち一つを選択。 グループ1 ■課題 telnet を使った WWW サーバへのアクセス グループ2 ■課題 telnet を使ったニュースサーバへのアクセス ■課題 NNTP コマンド グループ3 ■課題 SMTP の Verify コマンド ■課題 メール転送の詳細 以下の課題は3つのグループのうち java と C の二つの別なグループを選択する。 グループ1 ■課題 rfinger コマンド ■課題 wcat コマンド ■課題 javaのwcat グループ2 ■課題 nncat コマンド ■課題 javaによるNNTPクライアント グループ3 ■課題 mverify コマンド ■課題 javaによるSMTPクラアント 以下の課題は、グループを 一つ以上を選択する グループ1 ■課題 http-simple のコンパイルと実行 ■課題 ファイルの内容を返す http-simple ■課題 WWW サーバからのプログラムの実行 ■課題 アクセス制限 ■課題 javaによるサーバ グループ2 ■課題javaによるデータグラム・ブロードキャスト グループ3 ■課題javaによる移動エージェント --ネットワーク ネットワークは、物理的な線、例えば、 電話線 ISDN Ethrenet cable 10BASE-5,10BASE-2,10BASE-T 光ケーブル ATM交換機 などの上にプロトコルを定義することによって作られる。プロトコルには、 TCP/IP (Transmission Control Protocol/Internet Protocol) Netware NETBEUI X.25 など、さまざまなものがある。これらは任意に組み合わされる。電話線上の TCP/IPやEthernet上のNetware、X.25上のTCP/IPなどである。 情報工学科ではインターネットの主流であるTCP/IPを中心に勉強する。これら の上に、さらに、様々なサービスが定義される。 File Transfer (FTP) Mail (SMTP) Domain Name Service (BIND) Information Server (WWW) News (NNTP) Computer Supported Cooperated Work Personal Information Service (LDAP, ICQ) これらのサービスは、必然的にプロトコルに依存する。()内は、TCP/IPの 場合のサービス名である。WWW使用したければTCP/IPを用いる必要がある。 --TCP/IPの詳細 TCP/IPは、信頼性のある(reliable)双方向のストリーム転送サービス (stream transport service)を提供する通信プロトコルである(図1)。ス トリームとは、通信する2つのプロセス間に結合(connection)が形成され、複 数回に分けて送り出したデータでも、順番が入れ替わらないが、データの区切 りがわからなくなるような転送サービスである。UNIXのパイプは、双方向 ではなく、単方向であるが、同じストリームに分類される転送サービスである。 stream なお、C言語のライブラリ関数である fopen(), fgets(), fputs() なども、 ストリームと呼ばれることがある。これは、もともとランダム・アクセス可能 で、メモリ中の配列と同じようにアクセスするすることもできるファイルを、 まるでプロセス間通信のストリームと同じように扱うことができることに由来 する。ストリームの元の意味は、プロセス間通信である。 --層 TCP/IPによる通信では、図2に示すように、4つのプロトコル(規約、約束事) の層を構成される。TCP/IP自身は、TCP層と IP層という2つの層に分解される。 このようにさまざまなプロトコルが決められ、全体として層をなしている。こ の様子を、プロトコル・スタックと呼ぶ。 protocol TCP は、IP という通信プロトコルを利用して実現されている。IPは、(信頼 性がない)データグラム(datagram)転送サービスを提供する通信プロトコル である。データグラムでは、データの送り手と受けての間に結合が形成されず、 途中で順番が変ることや失われることがある。データグラムは、書留めではな い郵便に似ている。IPのデータグラムが配達されるときに使われる番地が、IP アドレスである。IPアドレスとしては、現在32ビットの整数が使われている。 TCP層の上は、応用層がある。この層では、ftp, rlogin, WWW, mnews, sendmail などの、TCP/IP を利用するプログラムの間の会話の方法が定義され る。TCP/IPを使った通信は、まるでプロセス同士が電話で会話をしているよう に進められる。普通の電話では、日本語を話す人と英語を話す人は、電話で情 報交換ができない。同様に、同じTCP/IPを使っていても、会話の約束事が違う と、まったく情報交換ができない。ゆえに、TCP/IPの上にさらに、情報交換の ためにさまざまなプロトコルが取り決められている。 TCP/IPの上に構築されているプロトコルの例を、表1に示す。ポート番号につ いては、後述する。 --表1 TCP/IPの上に構築されているプロトコルの例
表1 TCP/IPの上に構築されているプロトコルの例
ポート番号 名前目的
21 FTP(File Transfer Protocol) ファイル転送
23 Telnet 遠隔ログイン(telnet)
25 SMTP(Simple Mail Transfer Protocol) 電子メールの転送
79 finger fingerコマンド
80 HTTP(HyperText Transfer Protocol) WWWのデータ転送
119 NNTP(Network News Transfer Protocol) ネットワーク・ニュースの記事の転送
513 login 遠隔ログイン(rlogin)
IPのデータグラムを転送するためには、さまざまな物理的な媒体が使われる。 現在LANでは、インターネットやFDDIがよく使われいる。イーサネットは、同 軸ケーブルやより対線(Twisted Pair)を使ってデータを転送する。FDDIは、光 ケーブルを使っている。モデムなどを使ったシリアル回線では、PPP(Point to Point Protocol)というプロトコルの上に、IPデータグラムが流される。 データグラムは、ネットワーク通信では、最も基本的な転送サービスである。 IP上に構築された UDP(User Datagram Protocol)も、IPとほとんど同じ機能 を提供する。また、イーサネットやFDDIが提供する転送サービスも、データグ ラムである。 --■課題 サービス ping, telnet、ftp、smtp、nntp、DNS等の主なサービスではTCP、UDPのどちら が使用されているか調べなさい。またその理由をTCPとUDPの性質に基づいて説 明しなさい。/etc/services の役割は何か? --IPアドレスとドメイン名 TCP/IPによる通信は、通信相手のIPアドレス(32ビットの整数)とポート番号さ えわかれば、可能である。しかしながら、人間にとってIPアドレスは扱いやす いものではない。人間にとってわかりやすい記号の名前から、IPアドレスに変 換するサービスがあれば便利である。このサービスを、名前サービス(DNS, Domain Name Service)、それを行うプログラムを名前サーバという。 インターネットにおける名前サービスは、名前空間をドメイン(領域)に分割 して、階層的管理することで実現されている。これを、ドメイン・ネーム・サー ビス(Domain Name Service, DNS)という。DNSという言葉は、名前サービス を提供するプログラム(名前サーバ)を差すこともある。 DNSでは、主に名前をIPアドレスへ変換するサービスが使われている。その他 に、名前から電子メールの配送先、名前から名前サーバが動いているホストの 名前、名前から、名前サーバ自身の管理情報、逆にIPアドレスから名前を引く ためにも使われる。 --■課題 IPアドレスとイサーネットアドレス (必修) 32bitのIPアドレスは通常、 133.14.48.2 のように、8bitづつ区切った4つの数値(オクテット octet)で表す。 イサーネット上では個々のホストにイサーネットアドレス(Ethernet address) と呼ばれる48bitの番号が付いている。これらは、16進数12桁、あるいは、:で区切った6個の2桁の16進数 0:4:ac:90:60:22 で表すことが多い。 自分の使っているコンピュータのDNS名とIPアドレスとイーサネットアドレス を調べよ。この時、 man ifconfig man netstat man hostname man arp を参考にすること。pw では、/etc/netsart に、これらの情報がある。 DNS名とIPアドレスの対応は、DNS server に nslookup コマンド を使って問い合わせることができる。pw や nw のIPアドレスを nslookup コ マンドを使って調べよ。また、各研究室のコンピュータではどうか? 情報処理 センタのコンピュータではどうか? Internet 上のコンピュータでは? どのDNS が答えたかに注目せよ。また、Unix での /etc/resolv.conf に関する情報を man -k を使って調べよ。 --ネットワークとインターネット インターネットとは、複数のネットワークがつながったものである。特に、 Internet というと、アメリカのArpanetを起源とした Unix と TCP/IP を中心に構成されたインターネットをさす。 internetの図 ネットワークとは、ネット=網、ワーク=作品、ということで網状の構成を もつものという意味である。ここでは、特にコンピュータどうしを接続した ものをさす。ネットワークには基本的には二通りある。
  1. バス型のネットワーク 同じ線に複数のコンピュータを並列に接続するもの。安価であり、代表的な イサーネット(Ethernet)は爆発的に普及した。長さに制限があり(数百メートル) ビル内などの接続に向いている。特に、同じ線に接続された、すべてのコンピュータに 同時にデータ(パケットと呼ばれる)を送る機能(ブロードキャスト broadcast) があるのが普通であり、それが 特色になっている。
  2. ポイント対ポイント型のネットワーク 二つのコンピュータを繋げるもの。比較的長い距離をつなげられる。企業や大 学間の接続、また、家庭や1台のコンピュータをInternetにつなげる時には、 この方式を使う。この型のネットワークにはブロードキャストというのは意味 がない。送方向に同時に通信できるものを全二重(full duplex)と呼び、一度 には一方向しかデータが送れないものを半二重(half duplex)と呼ぶ。電話は、 通常、半二重であり、なんらかのプロトコルで全二重を模倣(Simulate)してい る。 最近では、ネットワークの能力を高めるために、 この二つを合わせたような星型の接続を行うことがおおい。 networkの図 Internetでは、このようなさまざまな形のネットワークが相互に接続されて いる。 --ホストとルータ ネットワークに接続されている計算機の中で、ネットワークに1ヵ所の出入り 口(インタフェース)を持っているものは、ホストと呼ばれる。2ヵ所以上の出 入り口を持っている計算機は、ルータと呼ばれる。ルータを使うことにより、 ネットワークとネットワークを接続することができる。ルータは、入ってきた IPのパケットのIPアドレスを見て、どのネットワークに送ればよいかを判断す る。ルータ専用に設計された計算機は特にスィッチング(Switching)ネットワークとか、 スィッチングハブなどと呼ばれる。 さらに、細かい固定長パケットを交換回線網上で高速に通信する機構を持つ ものをATM (Asynchronous Transmission Mode)という。琉球大学では、ATM を学科間の接続に使用している。 tcp1 図1で、左端と右端にあり、4層全てそろっている部分がホストである。 TCP/IPの通信は、ホストとホストの間で行われる。中央の、2層しかない部分 は、ルータである。ルータの仕事は、IP層において行われる。 ルータが接続するネットワーク には以下の三種類の接続(または、さらにそれらの混合)が考えられる。 ポイント対ポイント型のネットワークとポイント対ポイント型のネットワーク バス型のネットワークとポイント対ポイント型のネットワーク バス型のネットワークとバス型のネットワーク この時に問題になるのはブロードキャストの扱いである。それぞれの扱いの差に より、リピータやルータというように呼ばれる。 ブロードキャストをそのまま各ネットワークに配る (リピータ) ブロードキャストを通さない (ルータ) ルータを越えてブロードキャストを効率的に行うのは難しい。特に放送する ホストやネットワークを限定して放送を実現するプロトコルをマルチキャスト Multicastという。 --IPアドレスのネットワーク部分とホスト部分 インターネットのように、複数のネットワークからなる場合、IPアドレスは、 ネットワーク部分とホスト部分を持つ。インターネットが木構造を持つ場合は、 IPアドレスも同様の木構造を持つ。 例えば、琉球大学全体では、 32bit中16bitがネットワーク、16bitがホスト (Class Bと呼ばれる) だが、情報工学科では、 32bit中20bitがネットワーク、12bitがホスト という構成になっている。より小さな学科では、 32bit中24bitがネットワーク、8bitがホスト (Class C) などが使われる。 ネットワーク部分を32bitから抜き出すbit maskを定義することができる。 これはnetmaskと呼ばれる。ifconfig コマンドでは IPアドレスの他に netmaskも定義する必要がある。 --■課題 ARP (必修) IPアドレスは、イサーネット上で ARP (Address Resolution Protocol)を 通して、イサーネットアドレスと結びつけられる。
    1. ネットワークドライバが「このIPアドレスを持つイサーネット装置 はどれか」を問い合わせるブロードキャスト(放送)パケットを出す
    2. 該当する装置が「自分のイサーネットアドレス」を返す
    3. そのIPアドレス/イサーネットアドレスの組をarp tableに登録する
    arp コマンドを使って arp table を表示し、ping コマンドで arp table に ないアドレスにパケットを送ることにより、arp table にイサーネットアドレ スが登録される様子を観察せよ。 --■課題 ブロードキャスト ifconfig コマンドを使って、 コンピュータが接続しているTCP/IPの ブロードキャストアドレスを調べよ。また、そのブロードキャストアドレス に対してpingをしてみるとどうなるか。この結果からイサーネットの ブロードキャストの信頼性について考察せよ。 --■課題 ルータ 前の課題から、イサーネットではブロードキャストか届く範囲でしか通信できな いことがわかる。この範囲は物理的な制約とプロトコル的な制約できまる。 物理的な制約は、パケットをそのまま複製するリピータによって逃げることが できるが、プロトコル的な制約は逃げられない。また、リピータでも繋げられる 個数に制限が存在する。 逆に、ブロードキャストを多用するプロトコルでは、千を越えるコンピュータ をネットワークに接続することはできない。したがって、WAN (Wide Area Network) を実現するためには、複数のイサーネットをルータ で接続する。このルータのアドレスを知らないと、パケッ トをLAN(Local Area Network) を越えてInternetに出すことはできない。この 情報をrouting information (ラウティング情報)という。 netstat -r コマンドでコンピュータのラウティング情報を表示してみよ。 また traceroute コマンドを使って、Internet上の有名なサイトまでの パケット中継の様子を調べよ。 --仮想回線 TCP/IP では、プロセスとプロセスが、電話で会話をするように通信が行われ る。普通の電話で人間同士が話をするには、まず電話番号を指定して、話相手 に電話をとってもらわなければならない。TCP/IPでは、電話を掛ける方をクラ イアント・プロセス、電話を待つ方をサーバ・プロセスと言いう。 TCP/IPにおいて、プロセス間に形成されたストリーム通信路のことを、計算機 間に張られた物理的な回線に似ていることから、仮想的回線(virtual circuit)とも言う。TCP/IP では、回線を接続する段階では、クライアント・ プロセスとサーバ・プロセスは非対称である。一度仮想回線が接続された後は、 両方のプロセスは、TCP/IPのレベルでは、まったく対称的になる。 TCP/IPでプロセス間に仮想回線を開設するには、IPアドレスとポート番号が使 われる。ポート番号は、同じIPアドレスを持つホスト上で動いているプロセス を区別するために使われる。 図3に、通信路が開設される手順を示す。
    1. サーバ・プロセスがポート番号を指定して、要求受付用ポートを作る。 サーバ・プロセスは、クライアント・プロセスからの接続要求を待つ。 要求受付用ポートでは、データの送受信はできない。 tcp1
    2. クライアント・プロセスが通信用ポートを作る。このポートを、サーバ・ プロセスが動いているIPアドレスと、サーバ・プロセスが作った通信ポート のポート番号を使って、接続要求を行う(図3(a))。 tcp2
    3. 接続要求が受け付けられると、サーバ・プロセスには、新たに通信用ポー トが作られる(図3(b))。これは、特定のクライアントとの通信のために 使われる。 tcp3 こうして一度通信路が開設されると、クライアントとサーバは、どちらからで もデータを送り始めることができる。
    表1に示されているポート番号の例は、公に利用目的が決められているもので ある。それ以外に、1024以上のポート番号は、特に利用目的が決められていな いので、空いていれば利用者が自由に使ってもよい。 --プロセス間通信におけるクライアント・サーバ・モデル プロセス間通信は、本来自由に行うことができる。どのプロセスも自由にメッ セージを送信する権利がある。 クライアント・サーバ・モデルは、本来対称的なプロセスを最初にメッセージ を送る方(クライアント・プロセス)と受ける方(サーバ・プロセス)に分類 することで、プロセス間通信を構造化し、わかりやすくするものである。 TCP/IPの接続におけるクライアントとサーバの役割は、このプロセス間通信に おけるクライアント・サーバ・モデルの1つの例になっている。 その他に、クライアントとサーバという言葉は、サービスを受ける方と提供す る方の意味で使われることがある。インターネットにおけるプロセス間通信で は、多くの場合、サービスの授受の関係におけるクライアントとサーバと、プ ロセス間通信におけるクライアントとサーバが一致している。 --ソケット UNIX 上で動作するプログラムがTCP/IPの機能を使う場合、UNIXが提供するソ ケットというインタフェースを通じて利用することになる。ソケットは、 TCP/IP を始めとして、XNS, OSI などさまざまな通信プロトコルを UNIX 上で 使うために設計されたものである。TCP/IP だけを考えると、ソケットのイン タフェースは、繁雑であり、使いにくくなっている。 --telnet コマンドの使い方 telnet コマンドは、通常、次のように使われる。 ----------------------------------------------------------------------- % telnet host1 ----------------------------------------------------------------------- これは、次の省略形である。 ----------------------------------------------------------------------- % telnet host1 telnet ----------------------------------------------------------------------- ここで、第2引数の "telnet" は、TCP/IP のポート番号を示す記号である。 この記号は、/etc/services というファイルに次のように格納されている。 ----------------------------------------------------------------------- telnet 23/tcp ----------------------------------------------------------------------- telnet コマンドは、/etc/services ファイルを検索し、与えられた記号から ポート番号(この例では23)を得る。また、host1 の IP アドレスを、 /etc/hosts や DNS から得る。telnet コマンドは、この IP アドレスとポー ト番号の2つを使って、TCP/IP の接続を行う。(注意:NISが動いている場合 には、/etc/services や /etc/hosts の代わりに、NISのデータベース(マッ プ)が検索される。) telnet コマンドでは、次のように、ホストのIPアドレスとポート番号を 数字で打ち込むこともできる。 ----------------------------------------------------------------------- % telnet 133.13.30.131 23 ----------------------------------------------------------------------- ここで、133.13.30.131 とは、32ビットのIPアドレスを8ビットづつに区切り、 それぞれの8ビットの整数を10進数で表記したものである。よって、実際のIP アドレスは、次のようしてに計算できる。 ((((133-256)+13)-256)+30)-256+131 == 2232229507 よって、telnet コマンドに次のようIPアドレスを与えてもよい。 ----------------------------------------------------------------------- % telnet 2232229507 ----------------------------------------------------------------------- --telnet コマンドによる fingerd へのアクセス finger コマンドは、利用者の情報を表示するコマンドである。finger コマン ドは、ネットワーク経由で遠隔の利用者の情報を調べることもできる。 そのような finger コマンドの利用例を以下に示す。 ----------------------------------------------------------------------- % finger kono@pw001↓ [pw001] Login name: yas In real life: Yasushi SHINJO Directory: /home/teacher/yas Shell: /usr/local/bin/tcsh On since Sep 08 19:48:13 on pts/0 from top.ie.u-ryukyu. 9 minutes 29 seconds Idle Time No Plan. Login name: j94070 In real life: Yasushi [j94] Shinjo Directory: /home/b5/y94/j94070 Shell: /usr/local/bin/tcsh No Plan. Login name: j94077 In real life: Yasushi SHINJO Directory: /home/b2/y94/j94077 Shell: /usr/local/bin/tcsh No Plan. % ----------------------------------------------------------------------- ここで、下線を付けた部分が、利用者のタイプである。 この例で、finger コマンドは、クライアントとして、ホスト pw001 のポート 番号79(finger)のポートに対して、TCP/IP による仮想回線を開設する。そし て、次のような文字列を送る。 ----------------------------------------------------------------------- kono↓ ----------------------------------------------------------------------- すると、pw001 上のサーバ(fingerd, finger daemon)は、上の例で示した情 報をクライアントに返す。サーバは、データ転送が完了すると、TCP/IP の結 合を切断する。finger コマンド(クライアント)は、受け取ったデータをを 整形して利用者に対して表示する。 --■課題 telnet を使った finger サーバへのアクセス telnet コマンドを使って、finger サーバにアクセスして、自分の情報を検索 してみなさい。アクセス先のホストとしては、pw001-pw005, nirai, naha の中から選びなさい。その様子を、レポートに添付しなさい。script コマン ドや emacs 中のshell を使うとよい。また、nw001-nw020 に対して行ってみな さい。その結果と、前の結果を比較しなさい。 --telnet コマンドによる WWW サーバへのアクセス WWW (the World-Wide Web)では、TCP/IP の上にさらにHTTP(HyperText Transfer Protocol)と呼ばれるプロトコルを構築し、データの転送を行ってい る。Netscape や Lynx などのブラウザは、WWW サーバとの間に TCP/IP による 通信路を開設する。そして、クライアントは、必要なデータを得るための命令 を送る。この命令の形式を定めたものが、HTTP である。HTTP 通信プロトコル を受け付けるサーバを、HTTP サーバと呼ぶ。 表2に、HTTP で定義されている命令の例を示す。これらの命令に対して、サー バは、表3に定義されたような応答を行う。 --表2 HTTPで定義されている命令(methods)の例
    HTTPで定義されている命令(methods)の例
    命令 説明
    GET 情報を得る(ヘッダと本体の両方)
    HEAD 情報のヘッダのみを得る
    POST 新しく情報を作る
    --表3 HTTPで定義されている状態コードの例
    HTTPで定義されている状態コードの例
    状態コード 説明
    200 OK(エラーなし)
    301 要求されたデータが移動した
    400 要求の形式にエラーがある。
    404 要求されたデータが見つからない。
    --URL を持つデータへのアクセス たとえば、次のような URL を持つデータをアクセスすることを考える。 http://www.ie.u-ryukyu.ac.jp:80/Welcome.html Netscape などのクライアントは、まずホスト名 www.ie.u-ryukyu.ac.jp とポー ト番号80 を使ってサーバとの間に TCP/IP の通信路を開設する。そして、次 のような文字列を送る。 ----------------------------------------------------------------------- GET /Welcome.html HTTP/1.0↓ ↓ ----------------------------------------------------------------------- ここで、"GET" が命令の種類、"/Welcome.html" は、要求しているデータを表 わす URL (ファイル名)、"HTTP/1.0" は、使っているプロトコルのバージョン である。次の空行は、命令の終りを意味するものであり、必要である。 すると、サーバは、次のようなデータを送る。 ----------------------------------------------------------------------- HTTP/1.0 200 Document follows MIME-Version: 1.0 Server: CERN/3.0pre6 Date: Thursday, 07-Sep-95 13:14:34 GMT Content-Type: text/html Content-Length: 782 Last-Modified: Monday, 07-Aug-95 03:55:13 GMT University of Ryukyus WWW Home Page.

    Welcome to the University of the Ryukyus.



    Web Master of University of the Ryukyus.
    ----------------------------------------------------------------------- 最初の行が、状態行(status line)と呼ばれる、要求が成功したか失敗した かわ表わしている。"200" とは、成功したという意味である。2行目から最初 の空行までは、これから送るデータのメタ情報である。具体的には、データの 型や、サーバのバージョン、データが更新された日付と時刻、バイト数などが 記録されている。 最初の空行の次が、データの本体である。この例では、HTMLで記述されたデー タが返されている。サーバは、データ転送が完了すると、TCP/IP の結合を切 断する。 クライアントは、受け取ったデータをを整形して利用者に対して表示する。た とえば、インライン・イメージとして指定されたデータを続けてサーバに要求 して展開したり、フォントを変えたりして表示する。 --■課題 telnet を使った WWW サーバへのアクセス telnet コマンドを使って、WWW サーバにアクセスし、データを画面に表示さ せなさい。そのデータの URL とデータの先頭の20行程度を報告書に添付しな さい。 --telnet コマンドによる NNTP サーバへのアクセス NNTP(Network News Transfer Protocol) とは、ネットワーク・ニュースの記 事の転送や、記事の読み書きを行うためのプロトコルである。mnews や GNUS などのネットワーク・ニュースを読み書きするソフトウェアは、NNTP サーバ との間に TCP/IP による結合を形成する。そして、クライアントは、記事を要 求する文字列や、ニュース・グループの一覧を要求する文字列を送る。これに 対してサーバは、要求された記事やニュース・グループの一覧を返す。表4に、 クライアントからサーバへ送られるNNTPのコマンド、表5に、サーバからクラ イアントへ返され応答を示す。 --表4 NNTPのコマンド
    NNTPのコマンド
    GROUP ニュース・グループ名 ニュース・グループを選択する。結果として、記事の数、記事の番号 の上限と下限が返される。
    ARTICLE 記事番号 その記事の内容を得る。ニュース・グループが選択されている状態の 時に使える。
    ARTICLE <message-id> メッセージID <message-id> の記事の内容を得る。
    HELP ヘルプ・メッセージの表示
    QUIT 終了
    --表5 NNTPの応答
    NNTPの応答
    応答コード 説明
    100 ヘルプのテキストが続く。
    200 要求受け付け可能である(投稿可能)。
    201 要求受け付け可能である(投稿不可能)。
    205 通信路を切断する。
    211 ニュース・グループが選ばれた。
    記事の数、記事番号の上限、下限、ニュース・グループ名。
    400 サービスを中断する。
    411 そのようなニュース・グループがない。
    421 もうそのニュース・グループには次の記事がない。
    500 コマンドが認識できなった。
    501 コマンドの文法に誤りがあった。
    502 アクセスが制限されている。
    -- telnet コマンドを利用して、NNTP サーバに接続 以下に、telnet コマンドを利用して、NNTP サーバに接続した様子を示す。 ----------------------------------------------------------------------- 1: % telnet spn.ie.u-ryukyu.ac.jp nntp↓ 2: Trying 133.13.31.5 ... 3: Connected to spn.ie.u-ryukyu.ac.jp. 4: Escape character is '^]'. 5: 200 spn NNTP[auth] server version 1.5.12.1 (1 Jan 1995) ready at Thu Sep 7 22:56:28 1995 (posting ok). 6: help↓ 7: 100 This server accepts the following commands: 8: ARTICLE BODY GROUP 9: HEAD LAST LIST 10: NEXT POST QUIT 11: STAT NEWGROUPS HELP 12: IHAVE NEWNEWS SLAVE 13: DATE 14: 15: Additionally, the following extensions are supported: 16: 17: XHDR Retrieve a single header line from a range of articles. 18: LISTGROUP Retrieve a list of valid article-numbers. 19: XOVER Return news overview data. 20: XGTITLE Same as LIST NEWSGROUPS (for backward compatibility). 21: 22: Bugs to Stan Barber (Internet: nntp@academ.com) 23: . 24: quit↓ 25: 205 spn closing connection. Goodbye. 26: Connection closed by foreign host. 27: % ----------------------------------------------------------------------- ここで、下線で示した部分が、キーボードからのタイプである。この 例では、ホスト spn.ie.u-ryukyu.ac.jp のポート番号119(nntp)のポートに、 TCP/IPにより接続を試みている。2行目から4行目は、telnet コマンドによる 定型的な表示である。ここで、通信路が確立されている。すると、サーバは、 200 という応答を返している。これは、NNTP で定義されている応答であり、 サーバが、要求を受け付け可能であり、かつ、要求としては投稿要求も受け付 けることを意味している。200 以降の文字列は、コメントである。 第6行では、"help" というコマンドをサーバに送っている。これに対して、 サーバは、100 という応答に続けて、受け付け可能なコマンドなど、簡単な使 い方を返している。23行目に「.」からなる行がある。これが、1つのコマン ドに対する応答の終りを示している。 次に、24行において、"quit" というコマンドをサーバに送っている。これに たいして、サーバは、205 という応答を返し、続いて TCP/IP の結合を切断し ている。26行目は、telnet コマンドが生成したメッセージである。 --■課題 telnet を使ったニュースサーバへのアクセス telnet コマンドを使って、NNTP サーバ spn.ie.u-ryukyu.ac.jp にアクセス し、ネットワーク・ニュースの記事を画面に表示させなさい。その記事のニュー ス・グループ、ニュース・グループ内の番号、記事の先頭の20行程度を報告書 に添付しなさい。このとき、表NNTP のコマンドを使うとよい。 --■課題 NNTP コマンド その他の NNTP のコマンドを使ってみなさい。NNTP の定義は、RFC977 という ドキュメントにある。RFC977は、 /net/open/doc/rfc/rfc977.txt にある。 --telnet コマンドによる SMTP サーバへのアクセス SMTP(Simple Mail Transfer Protocol)とは、電子メールの転送を行うための プロトコルである。このプロトコルは、MTA (Mail Transfer Agent) と呼ばれ るプログラムの間で電子メールを配送するために使われている。MTA の例とし ては、UNIX 上で動作するsendmailと呼ばれるプログラムがあげられる。MTA は、一方が SMTP サーバ、もう一方が SMTP クライアントとなり、電子メール を転送する。表6に、SMTPで定義されている要求、表7に応答を示す。 --表6 SMTPで定義されている手続き -----------------------------------------------------------------------
    SMTPで定義されている手続き
    MAIL FROM:<reverse-path> 新しいメールの転送を開始する。 <reverse-path>は、エラーが起きた時の送り返し先のアドレス。
    RCPT TO:<forward-path> メールの送り先として <forward-path> を指定する。
    DATA メールのデータを送り始める。
    VRFY <login-name> メールの受け手を確認する。
    EXPN <ml-name> メーリング・リストの受取人を表示する。
    SEND FROM:<reverse-path> メールを転送する。
    HELO <domain> 最初に接続した時に自分自身を相手に知らせる。
    QUIT 接続を切る。
    --表7 SMTPの応答コード
    SMTPの応答コード
    コード 説明
    220 <domain> というドメインで要求受け付け可能である。
    250 そのアドレスへのメールは、受け付け可能である。
    251 そのアドレスは、ローカルには受取人がいない。
    --telnet コマンドを利用して、SMTP サーバに接続 以下に、telnet コマンドを利用して、SMTP サーバに接続した様子を示す。 ----------------------------------------------------------------------- 1: % telnet pw001 smtp↓ 2: Trying 133.13.30.131 ... 3: Connected to pw001. 4: Escape character is '^]'. 5: 220 pw001.st.ie.u-ryukyu.ac.jp Sendmail ALPHA-6.58/6.4J.6-UReecs-UG-21.0 ready at Fri, 8 Sep 1995 00:25:05 +0900 6: vrfy root↓ 7: 250 8: quit↓ 9: 221 pw001.st.ie.u-ryukyu.ac.jp closing connection 10: Connection closed by foreign host. 11: % ----------------------------------------------------------------------- ここで、下線で示した部分が、キーボードからのタイプである。この 例では、ホスト pw001 のポート番号25(smtp)のポートに、TCP/IPにより接続を 試みている。2行目から4行目は、telnet コマンドによる定型的な表示である。 ここで、接続が確立されている。すると、サーバは、220 という応答を返して いる。これは、SMTP で定義されている応答であり、サーバが、コマンド要求 を受け付け可能であり、 第6行では、"vrfy" (verify) というコマンドをサーバに送っている。これに対して、 サーバは、250 という応答に続けて、電子メールのアドレスを返している。 次に、8行において、"quit" というコマンドをサーバに送っている。これにた いして、サーバは、221 という応答を返し、続いて TCP/IP の結合を切断して いる。10行目は、telnet コマンドが生成したメッセージである。 --■課題 SMTP の Verify コマンド telnet コマンドを使って、pw001 と pw002 にアクセスし、自分のログイン名と 存在しないログイン名について、VRFY で調べてみなさい。そして、ホストに よる応答の違いを比較しなさい。 --■課題 メール転送の詳細 pw001 以外のホストで、mail コマンドに -v オプションを付けて、メールを送っ て、その様子を観察しなさい。すると、SMTP による電子メールの配送の様子 が観察される。ただし、mail -v では、電子メールのデータ(DATAの部分)は、 表示されない。ここでデータとは、To: 行や From: 行などのヘッダも含む。 SMTP のレベルにおいては、データの部分の To: 行は、配送には使われない。 その代わりに、SMTP で定義されている RCPT が使われる。 SMTP コマンドを使って電子メールを送ってみなさい。SMTP の定義は、RFC821 というドキュメントにある。RFC821は、 /net/open/doc/rfc/rfc821.txt にある。mail -v の結果を参考にするとよい。 --ネットワーク・プログラミング --クライアントの作成 telnet でやったことを、C言語のプログラムで実現する。 stream ライブラリを使う。 --streamライブラリ initport() と fdopen2() この実験では、Don Libes 氏により開発された stream ライブラリを用いる。 これは、UNIX 上で TCP/IP を使うプログラムを書きやすくするためのライブ ラリである。このライブラリを使うことで、UNIX固有の繁雑なソケットを利用 することなく、もともとの TCP/IP のモデル(3.1節の図3参照)に近い形で TCP/IPを利用するプログラムを書くことが可能になる。 --initport() steam ライブラリでは、initport() という関数が、中心的な役割を果たす。 initport() は、TCP/IP のクライアント側(接続を行う方)でも、サーバ側 (接続されるのを待つ方)でも使われる。この項では、クライアント側の使い 方を示す。 initport() は、クライアント側では、次の2種類の形式で使われる。 ----------------------------------------------------------------------- #include #include #include #include "inet.h" int s = initport(PORT_NUMBER(port), CLIENT,SOCK_STREAM,host); int s = initport(PORT_NAME(name),CLIENT,SOCK_STREAM,host); int port ; char -name ; char -host; ----------------------------------------------------------------------- 前者は、ポート番号を指定して、TCP/IP の接続を確立するものである(3.1節 の図3参照)。重要な引数は、TCP/IP のポート番号 port と、ホスト名 host である。その他の引数 CLIENT と SOCK_STREAM は、定数であ。これらは、ク ライアント側で使う限り、必ず指定されなければならない。 結果として、1つのファイル記述子 s が返される。これは、TCP/IP の双方向 ストリームに対応している。よって返されたファイル記述子に対して次のよう に write() システム・コールでデータを書き込むと、そのデータは、接続先 に送り届けられる。 write( s, buf, size ); 逆に、接続先から送られてきたデータは、read() システム・コールにより受 け取ることができる。 read( s, buf, size ); 1つのファイル記述子にたいして、read(),write() もと利用することができ る。これは、ファイルを読み書き(O_RDWR)モードで開いた時と似ている。 もう1つの形式は、ポート番号の代わりにポート名(サービス名)を指定する 方法である。たとえば、"telnet" というサービスの場合、次のようにして使 うことができる。 s = initport(PORT_NAME("telnet"),CLIENT,SOCK_STREAM,host); エラーが生じると、initport() は、-1 を返す。 なお、ネットワーク・プログラミングの教科書の多くは、ソケットを直接利用 するように書かれている。この実験においても、stream ライブラリを使うこ となく、直接ソケットを利用してプログラムを作成してもよい。 --fdopen2() fdopen2() は、この実験のために標準のライブラリ関数 fdopen() を拡張して 作っ関数である。fdopen() は、open() システム・コールなどで開いたファイ ルについても、fprintf(), fgets(), fputs() などのバッファリング機能付の 入出力関数を使いたい時に使われる。たとえば、次のようにして使われる。 ----------------------------------------------------------------------- FILE -f ; fd = open("file1",O_RDONLY); .... f = fdopen(fd, "r") fgets( buff,sizeof(buff),f ); ----------------------------------------------------------------------- これにより、open() で開いたファイルについても、バッファリング機能付の 入出力関数が使えるようになる。fdopen() は、open() 以外にも、pipe() や dup() の結果にも使われる。 fdopen2() は、TCP/IPの通信用ポートに対応しているのように、入出力可能な ファイル記述子について、2つの入出用と出力用の FILE - を返す。 ----------------------------------------------------------------------- FILE -fin, -fout ; fd = initport(PORT_NAME("finger"),CLIENT,SOCK_STREAM,host); ... fdopen2(fd,&fin,&fout) fprintf( fout, "%s\n", who ); fflush( fout ); fgets( buff, sizeof(buff), fin ); ----------------------------------------------------------------------- fdopen2() の第1引数 fd には、initport() や connect(), accept() で作ら れた入出力可能(read()システム・コールもwrite() システム・コールも使え る)ファイル記述子を指定する。結果として作られた FILE - は、第2、第3 引数として与えられた FILE - へのポインタで示された番地に格納される。 fdopen2() は、エラーが起きた時には、0, 成功した時には、0 以外が返され る。 fdopen2() のソース・プログラムは、 /net/open/classes/slab/info2/lib/fdopen2.c にある。 --コンパイルとリンク initport() を使うプログラムは、コンパイル時に "inet.h" というヘッダ・ ファイルを読み込まなければならない。これは、 /net/open/classes/slab/info2/include/ に置かれている。よって、コンパイ ル時に、cc コマンドに次のようなオプションを与える必要がある。 % cc -I/net/open/classes/slab/info2/include/ -c file.c また、initport() などの関数は、次のいずれかのファイルに格納されている。 /net/open/classes/slab/info2/lib/libinfo2-sun4.a Sun用 /net/open/classes/slab/info2/lib/libinfo2-rs6000.a IBM用 (BSD/OS用は/net/open/classes/slab/info2の下にソースから自分で作成すること) これを利用するためには、リンク時に次のように指定する。 % cc -o commmand file.o /net/open/classes/slab/info2/lib/libinfo2-sun4.a または、次のように -L, -l オプションを用いて指定する。 % cc -o commmand file.o -L/net/open/classes/slab/info2/lib/ -linfo2-sun4 以下の実験で使うコマンドについては、 /net/open/classes/slab/info2/2-tcp/Makefile に、コンパイルとリンクのた めの設定が格納されている。これを利用するとよい。 --finger クライアントのコンパイルと実行 遠隔のfingerサーバに対して問い合わせを行うコマンド、rfinger (remote finter)のソース・プログラムを、以下のファイルに示す。 ----------------------------------------------------------------------- /net/open/classes/slab/info2/2-tcp/rfinger.c: ----------------------------------------------------------------------- 1: 2: /- 3: rfinger.c -- Remote Finger / 遠隔専用 finger コマンド。 4: $Header: /net/home/cvs/teacher/kono/os/ex/tcp/network.ind,v 1.1.1.1 2007/12/18 03:39:44 kono Exp $ 5: Start: 1995/09/08 21:04:33 6: -/ 7: #include 8: #include 9: #include 10: #include 11: #include "inet.h" 12: 13: main( argc,argv ) 14: int argc ; 15: char -argv[] ; 16: { 17: /- 引数は、コマンド名を入れて3個。 -/ 18: if( argc != 3 ) 19: { 20: fprintf( stdout,"Usage: %s host \"who\"\n",argv[0] ); 21: exit( -1 ); 22: } 23: rfinter( argv[1],argv[2] ); 24: } 25: 26: #define BUFFSIZE 1024 27: 28: rfinter( host,who ) 29: char -host ; /- ホスト名 -/ 30: char -who ; /- 調べたい人のキー -/ 31: { 32: int fd ; 33: char buff[BUFFSIZE] ; 34: int count ; 35: 36: /- buff で確保されているメモリよりも長い who については、エラーにする。-/ 37: if( strlen(who) >= BUFFSIZE-2 ) 38: { 39: fprintf(stderr,"search key too long: \n%s\n",who ); 40: exit( -1 ); 41: } 42: /- 43: initport() 関数により、TCP/IPのクライアント側における通信用ポートを設 44: 定する。このとき、ポート名と接続先のホストを指定する。この関数により、 45: TCI/IPの通信路が開設され、read(), write() により通信を行うことが可能に 46: なる。エラーが起きたときには、-1 が返される。 47: -/ 48: fd = initport(PORT_NAME("finger"),CLIENT,SOCK_STREAM,host); 49: if( fd < 0 ) 50: { 51: fprintf(stderr,"initport(,,host:%s) = %d\n", 52: host, fd); 53: exit( -1 ); 54: } 55: 56: /- 57: 通信内容を、バッファ buff に作る。このとき、sprintf() を使うと便利であ 58: る。これは、printf() と同じ形式の引数をとることができる。結果は、画面 59: に表示されるのではなく、buff (string)に保存される。最後の '\n' は、必 60: 要である。 61: -/ 62: sprintf( buff,"%s\n", who ); 63: count = strlen( buff ); 64: 65: /- 66: 通信用ポートに対応しているファイル記述子を引数としてwrite() システム・ 67: コールを発行することで、TCP/IPによるプロセス間通信が行われる。これによ 68: り、buff 番地から count バイトのデータが、通信相手に送られる。 69: -/ 70: if( write(fd,buff,count) != count ) 71: { 72: perror("write() to socket"); 73: exit( -1 ); 74: } 75: /- 76: 通信用ポートに対応しているファイル記述子を引数として read() システム・ 77: コールを発行することにより、TCP/IPによるプロセス間通信が行われる。これ 78: により、通信相手から送られてきたデータが、buff 番地から始まる BUFFSIZE 79: バイトの領域へ書き込まれる。read() システム・コールのリターン・バリュー 80: は、実際に送られてきたデータのバイト数である。 81: -/ 82: while( (count=read(fd,buff,BUFFSIZE)) > 0 ) 83: { 84: if( write(1,buff,count) == -1 ) 85: { 86: perror("stdout"); 87: exit( 1 ); 88: } 89: } 90: close( fd ); /- TCP/IP connection を閉じる。-/ 91: close( 1 ); /- 標準出力のファイルを閉じる。-/ 92: } 93: /- --------------------- rfinger.c --------------------- -/ 94: static char rcsid[] = 95: "$Header: /net/home/cvs/teacher/kono/os/ex/tcp/network.ind,v 1.1.1.1 2007/12/18 03:39:44 kono Exp $" ; ----------------------------------------------------------------------- --■課題 rfinger コマンド rfinger.c をコンパイルして、実行してみなさい。 ----------------------------------------------------------------------- % cp /net/open/classes/slab/info2/2-tcp/{rfinger.c,Makefile} . % make rfinger % ./rfinger pw001 $USER ----------------------------------------------------------------------- 報告書には、自分の情報を rfinger で調べた結果を示しなさい。ログイン名 で引いた時と、finger name として設定している文字列で引いたときの結果を 示しなさい。もし、finger name をまだ設定していないならば、chfn コマン ドで設定しなさい。このとき、設定の前後で、表示や検索の様子がどう変わる かを調べて報告しなさい。 --Javaによるfinger Java で finger を実現するためには、Class Socket を使う。以下の プログラム で、 theSocket = new Socket(hostname, port); がSocketのインスタンス(実体)を取って来ている部分である。これから、 ps = new PrintStream(theSocket.getOutputStream()); によってストリームを取り出す。後は、このストリームに対して、 while((s = theFingerStream.readLine()) != null) ... を繰り返すことによりデータをソケットから読み出すことができる。 このプログラムをコンパイルするには、 javac Finger.java とする。すると、 Finger.class が出来るので、 java Finger pw001 により実行することができる。 実際にプログラムをコンパイルして実行できることを確認せよ。 java Program は、applet と呼ばれるHTMLから呼ばれるプログラムとしても 動作させることができる。applet の作成方法を自分で調べ、 Finger.java を書き直し、FingerApplet.java を 作り、適当なHTMLページより Finger を起動してみよ。これらのjavaプログラム は、HTMLページを表示するブラウザ(NetscapeやInternet Explore)で実行される。 様々なブラウザで実行してみて、その結果に関して考察せよ。 --WWW クライアントの作成 --■課題 wcat コマンド WWWサーバからデータを得るプログラムを作りなさい。そのプログラムの名前 を、wcat とする。wcat のプログラムの骨組みを /net/open/classes/slab/info2/2-tcp/wcat.c に示す。これをコピーして、使いなさい。 ----------------------------------------------------------------------- % cp /net/open/classes/slab/info2/2-tcp/wcat.c . ----------------------------------------------------------------------- wcat コマンドは、次のように3つの引数を与えて利用するものとする。 ----------------------------------------------------------------------- % ./wcat host port file ----------------------------------------------------------------------- ここで、host は、ホスト名、port は、TCP/IP のポート番号、file は、得る べきファイル名である。これは、URL の文法で記述すると、次のようになる。 http://host:port/file なお、wcat では、ポート番号の引数を省略しないものとする(省略可能なよ うに工夫してもよい)。HTTP プロトコルで用いられる標準のポート番号は、 80である。 wcat のプログラムを作る時に、rfinger.c を参考にするとよ い。initport() では、ポート名(サービス名)ではなく、ポート番号を用い る形式を利用するとよい。 ----------------------------------------------------------------------- fd = initport(PORT_NUMBER(port),CLIENT,SOCK_STREAM,host); ----------------------------------------------------------------------- HTTP では、ヘッダ部分の行末に、キャリッジ・リターン(carrige return, CR)とライン・フィード(Line feed, LF)の両方が必要であると定められてい る。UNIX では、通常ライン・フィード(ニュー・ライン、New Line, NL と呼 ばれることもある)だけが行末の記号として使われる。よって、画面に文字列 を表示し、改行したい場合は、次のようなプログラムが使われる。 printf("Hello,world\n"); これは、HTTP では、次のようにしなければならない。 printf("Hello,world\r\n"); ここで、'\r' がキャリッジ・リターン、'\n' がライン・フィードである。い ずれも、ソース・プログラム上では2文字に見えるが、Cコンパイラにより、 1文字に変換される。それぞれ、アスキーでは、13(0x0d), 10(0x0a) である。 --■課題 javaのwcat wcat.c と同様のプログラムである、 FetchURL.java をコンパイルして実行せよ。また、プログラムを変更して、applet としても 実行できるようにせよ。 --NNTP クライアントの作成 --■課題 nncat コマンド NNTPサーバから記事を1つ得るプログラムを作りなさい。そのプログラムの名 前を、nncat とする。nncat のプログラムの骨組みを /net/open/classes/slab/info2/2-tcp/nncat.c に示す。これをコピーして、 使いなさい。 ----------------------------------------------------------------------- % cp /net/open/classes/slab/info2/2-tcp/nncat.c . ----------------------------------------------------------------------- nncat コマンドは、次のように3つの引数を与えて利用するものとする。 ----------------------------------------------------------------------- % ./nncat host newsgroup number ----------------------------------------------------------------------- ここで、host は、NNTPサーバが動いているホストの名前newsgroup は、ニュー ス・グループ、number は記事番号である。HTTP プロトコルで用いられる標準 のポート番号は、119(nntp) である。initport() では、PORT_NAME("nntp") の形式を利用するとよい。 報告書には、作成した nncat コマンドの動作例を示しなさい。NNTPサーバが 動いているホストとしては、spn (spn.ie.u-ryukyu.ac.jp) を指定しなさい。 NNTP でやり取りされるデータの行末には、キャリッジ・リターン(carrige return, CR)とライン・フィード(Line feed, LF)の両方が必要であると定め られている。UNIX では、通常ライン・フィード(ニュー・ライン、New Line, NL と呼ばれることもある)だけが行末の記号として使われる。よって、画面 に文字列を表示し、改行したい場合は、次のようなプログラムが使われる。 printf("Hello,world\n"); これは、NNTP では、次のようにしなければならない。 printf("Hello,world\r\n"); ここで、'\r' がキャリッジ・リターン、'\n' がライン・フィードである。い ずれも、ソース・プログラム上では2文字に見えるが、Cコンパイラにより、 1文字に変換される。それぞれ、アスキーでは、13(0x0d), 10(0x0a) である。 余裕があれば、画面に表示する前に、UNIX に合わせて行末のキャリッジ・リ ターンのコードを削除するようにしなさい。 --■課題 javaによるNNTPクライアント wcat.c と同様のプログラム をJava言語を使って作りなさい GenericClient.javaとする。 ログラムの骨組みを /net/open/classes/slab/info2/6-tcp/{gclient.c, GenericClient.java}、 房ィ す。これを 修正して、javaによるNNTPクライアント作成せよ。 また、プログラムを変更して、applet としても 実行できるようにせよ。 このプログラムは、琉大内部のニュースグループを外部から読むことを 可能にすると思われる。実際にそのようなことが可能かどうか確かめよ。 また、これに関するjavaの対処法に関して考察せよ。 --SMTP クライアントの作成 --■課題 mverify コマンド SMTPサーバに対して、VRFY 手続きを送り、受取人のアドレスを確認するプロ グラムを作りなさい。そのプログラムの名前を、mverify とする。mverify の プログラムの骨組みを /net/open/classes/slab/info2/2-tcp/mverify.c に示す。これをコピーして、使いなさい。 ----------------------------------------------------------------------- % cp /net/open/classes/slab/info2/2-tcp/mverify.c . ----------------------------------------------------------------------- mverify コマンドは、次のように2つの引数を与えて利用するものとする。 ----------------------------------------------------------------------- % ./mverify host who ----------------------------------------------------------------------- ここで、host は、SMTPサーバ(sendmailデーモン)が動いているホストの名前、 who は確認するアドレスである。SMTPプロトコルで用いられる標準のポート番 号は、25(smtp) である。initport() では、PORT_NAME("smtp") の形式を利用 するとよい。 報告書には、作成した mverify コマンドの動作例を示しなさい。NNTPサーバ が動いているホストとしては、pw001 を指定しなさい。自分のアドレスを確認 してみなさい。 ----------------------------------------------------------------------- % ./mverify pw001 $USER ----------------------------------------------------------------------- --■課題 javaによるSMTPクラアント wcat.c と同様のプログラムである、 FetchURL.java を修正して、javaによるSMTPクライアント作成せよ。 また、プログラムを変更して、applet としても 実行できるようにせよ。 このプログラムは、個人のメールを外部から出す 可能にすると思われる。実際にそのようなことが可能かどうか確かめよ。 また、これに関するjavaの対処法に関して考察せよ。 -- サーバのプログラミング -- WWWサーバの改良 これまでHTTP, NNTP, または、SMTP のクライアントのプログラムを作成し た。この節では、簡単な HTTP サーバのプログラムを解読し、機能拡張と改良 を行う。 --initport()(サーバ側) これまでstreamライブラリのinitport()関数のうち、クライアント側の 使い方を示した。ここでは、サーバ側の使い方を示す。サーバ側では、 initport() は、次のような形式で使われる。 ----------------------------------------------------------------------- #include #include #include #include #include "inet.h" s = initport( PORT_NUMBER(port),SERVER,SOCK_STREAM ); int port ; ----------------------------------------------------------------------- これにより、サーバ側に受け付け用のTCP/IPのポートが作られる(3.1節の 図3参照)。そのポート番号は、引数portにより指定される。initport()に対 するその他の引数 (SERVER, SOCK_STREAM) は、定数である。これらは、サー バ側で使う限り、必ず指定されなければならない。 結果として、1つのファイル記述子 s が返される。これは、TCP/IP のサーバ 側における受け付け用のポートと対応している。受け付け用のポートとは、ポー ト番号を保持し、クライアントからの接続要求を受け付けるためのものである。 このポートを通じて、データを送受することはできない。すなわち、このファ イル・記述子に対して、read() システム・コールや write() システム・コー ルにより、入出力を行うことができない。実際に入出力を行うためのポートは、 次の select_server_stream() によって得られる。 ----------------------------------------------------------------------- int client = select_server_stream(s,&fds); int s ; fd_set fds ; ----------------------------------------------------------------------- select_server_stream() の引数 s は、initport() により返されたファイル 記述子である。fdsは、select_server_stream() 内部で複数の接続扱うための 作業用変数である。fd_set とは、ファイル記述子の集合(配列)を保持する ためのビット配列である。最初に FD_ZERO() により初期化されなければなら ない。それ以後は、select_server_stream() により管理される。 select_server_stream() は、クライアントからの接続要求が来るか、クライ アントからのデータが到着するまで待つ。クライアントからの接続要求が来る と、それを受け付ける。その結果として、クライアントとの間で双方向のスト リームにより通信可能なファイル記述子を返す。 select_server_stream() は、1つのサーバ・プロセスで複数のクライアント を同時に扱う事を可能にする。サーバ・プロセスは、複数のクライアントの間 に、複数のTCP/IPの接続を同時に保持することができる。そして、それらの接 続の中で、データが届いたものを選び、返す機能がある。 select_server_stream() により返されたファイル記述子は、クライアントか らのデータが到着している、入出力可能なTCP/IPの通信ポートに対応している。 サーバの処理は、この通信ポートから要求を読みだし、それに応じた処理わ行 い、結果をこの通信ポートに書き出すことである。 なお、ネットワーク・プログラミングの教科書の多くは、ソケットを直接利用 するように書かれている。この実験においても、stream ライブラリを使うこ となく、直接ソケットを利用してプログラムを作成してもよい。 --httpd-simple ここでは、簡単な HTTP サーバ(WWWのサーバ)を例に、TCP/IPのサーバのプ ログラムの概要を示す。サーバのソース・プログラムを、次のファイルに示す。 ----------------------------------------------------------------------- /net/open/classes/slab/info2/2-tcp/http-simple.c: ----------------------------------------------------------------------- --■課題 http-simple のコンパイルと実行 http-simple.c をコンパイルして、実行してみなさい。 ----------------------------------------------------------------------- % cp /net/open/classes/slab/info2/2-tcp/{http-simple.c,Makefile} . % make http-simple % ----------------------------------------------------------------------- ウィンドウを2つ用意しなさい。1つのウィンドウで、次のように http-simple を実行しなさい。 ----------------------------------------------------------------------- % ./http-simple ~/public_html/ http://pw001:13520/ ----------------------------------------------------------------------- ~/public_html/ は、このサーバが提供するデータを含んでいるディレクトリ を指定する。あらかじめ作成しておくこと。ここで、 http-simple が表示し た URL を記憶しなさい。実際には、ホスト名やポート番号が異なるはずであ る。 ★注意: http-simple は、サーバ・プロセスなので、自動的に終了しない。 実験が終了したら、必ず^Cやkillコマンドでこのプロセスを終了さなさい。も し、実験に使用したプロセスが残されていた場合、この減点の対象とする。 もう1つのウィンドウで、次のように Netscape を起動しなさい。 (lynx でもよい。) ----------------------------------------------------------------------- % Netscape http://pw001:13520/Welcome.html ----------------------------------------------------------------------- ここで Netscape の引数は、先ほど ./http-simple が起動時に表示した URL に 引き続き、何か適当な文字列(これ例では、"Welcome.html")を続けたもので ある。 あらかじめ Netscape を起動していた場合、Open URL を使って、URL http://pw001:13520/Welcome.html の資源を得なさい。すると、次のような画 面が現われるはずである。 ----------------------------------------------------------------------- request[/Welcome.html] ----------------------------------------------------------------------- これは、http-simple.c:perform() の中で、次の fprintf() の呼び出しに対 応している。 ----------------------------------------------------------------------- fprintf( fout,"request[%s]\n",filename ); ----------------------------------------------------------------------- --■課題 ファイルの内容を返す http-simple http-simple.c は、要求されたURLを、そのままクライアントに返す機能しか ない。これを改良して、ファイルを開き、その内容を返すようにしなさい。与 えられたファイル名を使ってファイルを、fopen() で開き、fread() で読み込 み、fwrite() でクライアントに返すとよい。このとき、ファイル名の拡張子 が".html" の場合には、"Content-Type: text/html\r\n" を返しなさい。また、 ".gif" の場合には、"Content-Type: image/gif\r\n" を返しなさい。実際の HTTP サーバにならい、ファイルの大きさや日付を返すようにしてもよい。 ファイルが見つからない時には、HTTP のエラーである 404 を返しなさい。 HTTP で、ヘッダと本体を分ける空行を忘れないようにしなさい。 --■課題 WWW サーバからのプログラムの実行 課題13では、ファイルを開き、その内容を返していた。ファイルの内容ではな く、プログラムを実行してその結果を返すようなプログラムを作りなさい。実 行するプログラムとしては、次のようなものが考えられる。 (1) who (2) finger (3) ps プログラムを実行し、その結果を取り込むためには、popen() ライブラリ関数 を使うとよい。 内容の型としては、"Content-Type: text/plain\r\n" を付けるとよい。余裕 があれば、"Content-Type: text/html\r\n" にして、その他の文字列とともに、 プログラムの出力に ,
    ,
    を付けて返すようにし なさい。 --■課題 アクセス制限 http-simple.c は、どのホストからの要求も受け付けている。特定のホストか らの要求しか受け付けないように、改良しなさい。現在のプログラムは、クラ イアントのIPアドレスをprint_client() により表示している。この課題では、 IPアドレスを表示するだけでなく、その内容を調べて、アクセスを許すか許さ ないかを決めなさい。たとえば、次のような方法が考えられる。 (1) 特定のホストだけからのアクセスを許す。 (2) bw0? というホストからのアクセスを許す。 (3) 133.13.30.- というパタンのIPアドレスを持つホストからのアクセスのみ を許す。 (4) 133.13.-.- というパタンのIPアドレスを持つホストからのアクセスのみ を許す。 (5) -.u-ryukyu.ac.jp というホスト名を持つホストからのアクセスのみ を許す。 IP アドレスからホスト名を得るには、ライブラリ関数gethostbyaddr()を使う とよい。 --■課題 javaによるサーバ javaによるサーバは、サーブレットなどと呼ばれる。 HttpMirror.javaをコンパイルして、実行してみなさい。 HttpMirror を次のように実行しなさい。 ---------------------------------------------------------------------- % java HttpMirror 13520 ---------------------------------------------------------------------- このサーバはリクエストされたファイルを返す代わりに、そのリクエストをク ライアントにそのままミラーで応答する。 HttpMirror.java を修正して、http-simple と同様の拡張をおこなえ。 HTMLファイルの中身を返す プログラムを実行した結果を返す アクセス制限を実現する ★注意: http-simple、HttpMirrorは、サーバ・プロセスなので、自動的に終 了しない。実験が終了したら、必ず^Cやkillコマンドでこのプロセスを終了さ なさい。もし、実験に使用したプロセスが残されていた場合、この減点の対象 とする。 --■課題 javaによるデータグラム・ブロードキャスト ブロードキャストは、特にイサーネット上で実装されている ブロードキャスト・パケットを用いて、同一ネットワーク・ セグメント上の不特定多数のホストに同時にパケットを送る ことである。 JavaのMulticastSocketを使ったロードキャスト を行なうプログラムを作成 しなさい。MulticastSniffer.java、MulticastSender.java の骨組みは /net/open/classes/slab/info2/6-tcp/java の下にある。 まず、パケットがSenderから複数のSinifferに同時に送られることを確認 するだけのプログラムを作成する。 すべてのメッセージが確実に到着するかしないかを 確認せよ。ブロードキャスト・パケットに関する信頼性に関して 考察せよ。 放送する複数のホストを前もって決めておき、そのホスト全部にパケット を同時に送ることをマルチキャストという。 信頼性のあるマルチキャスト方式に関して調べ、java での実装に 関して報告せよ。 --■課題 javaによる移動エージェント 次に移動エージェントプログラミングを実現するAgletsパッケージが /net/open/java/Aglets1.0.3/ にある。 これに含まれるサンプルプログラムを使用してみなさい。 /net/open/java/Aglets1.0.3/samples にある。 Agletsに関する ドキュメント これらのサンプルを参考にエージェントの巡回、並列派遣、クローンニグと Javaのソケットを使用した、エージェントシステムを作成し、そのシステムを 説明しなさい。 --報告書 この章の全ての実験課題について、1通の報告書を提出しなさい。それぞれの 実験について、作成したプログラムとその説明(4.1を除く)、および、その 実行結果を付けなさい。この実験では、プログラムの動きを説明するフローチャー トを付加する必要はない。開発環境と実行環境(計算機、オペレーティング・ システムのバージョン、コンパイラ)を載せなさい。 実験について、作成したプログラムとその説明(4.1を除く)、および、その 実行結果を付けなさい。この実験では、プログラムの動きを説明するフローチャー トを付加する必要はない。開発環境と実行環境(計算機、オペレーティング・ システムのバージョン、コンパイラ)を載せなさい。 その他、この実験を通じて得たことを報告しなさい。 この実験に要した時間(単位は時間)を書きなさい。 この実験指導書の改善点を書きなさい。 --一般的な注意: 報告書を、日本語で記述しなさい。プログラム、表、図、数式の羅列は、日本 語ではない。それらは、必ず本文中から参照しなさい。たとえば、「○○を図 1に示す」、あるいは、「○○を以下に示す。<以下、参照しているものを続 ける>」といった形式を使うとよい。数学における証明のように論理的に記述 する。主語と述語を明確に書くとよい。 --参考資料 /net/open/doc/inet/protocols/http-1.0.txt HTTP 1.0 の仕様。テキスト形式。 http://www.w3.org/hypertext/WWW/Protocols/Overview.html HTTPプロトコルについて。 /net/open/doc/rfc/rfc821.txt SMTP (Simple Mail Transfer Protocol) /net/open/doc/rfc/rfc977.txt NNTP (Network News Transfer Protocol) --付録 --streamライブラリ(sized_ioライブラリ)の README ファイル README ファイル streadm ライブラリ(sized_io ライブラリ)の入手先。 archieで sized_io を検索するとよい。 または、 これ を使おう。