実験6
通信基礎実験
1 目的 ネットワークを通じてデータ転送を行うことを体験的に学ぶために、本実験ではT CP/IPプロトコルを使い、ワークステーション間で通信を行うクライアントサー バモデルのプログラムを作成する。 2 解説 1 ネットワークとプロトコル ネットワーク(コンピュータネットワーク)とは2台以上のコンピュータが何 らかの線でつながったものである。しかし、線で接続されているだけではコンピ ュータ間で通信を行うことが出来ず、コンピュータ間の通信を行う物理的な手順 ネットワークカードなどのハードウェアに関する通信方法 論理的な手順 ア ( )、 ( プリケーションにおけるソフトウェアに関する通信方法)を与える必要がある。 このようなコンピュータ間の通信手段の取り決めをプロトコルという。 インターネットとは、大学や企業などの組織内で構築されたネットワークを相 互に接続する広域ネットワークで、インターネットプロトコル(IP)と呼ばれ るプロトコルによって通信が行われる。通信線には電話線、イーサネットケーブ ル、同軸ケーブル、光ケーブル、鳩などがある。 2 TCP/IPAdvanced Research Projects TCP/IPはアメリカ国防省の高等研究計画局( ARPA)のネットワークであるARPANET上で開発された。当初 Agency , ARPANETはパケット交換を使用して広域ネットワークを構築するために設 計されたが、TCP/IPプロトコルはLANにも適用されるようになった。 年代始めに発表されたUNIX4.2BSDにおいてTCP/IPが実 1980 装されていたことから、ワークステーションの通信プロトコルとして実質的な標 準となり、1983 年にはARPANETの標準プロトコルとして使用されるよう になった。 3 UDP UDPはトランスポート層のプロトコルで、アプリケーションからアプリケー ションへの通信を提供する。IPがインターネットアドレスをともにパケットの 交換を行うのに対し、UDPはポートという概念でパケットの交換を行う。IP
UDPはTCPのコネクション型通信と比べ、信頼性の低いコネクションレス 型の通信を行い、誤り制御、順序付け、フロー制御を行わない。そのため、UD Pモジュールの処理が単純になり、TCPに比べ、高速なデータ転送が可能にな る。このようにIPがもつ最低限の機能のみをユーザーアプリケーションに提供 しているため、誤り制御などの信頼性については上位のプロトコルで対処する必 要がある。 4 IPアドレス ネットワークに接続されたパソコンやワークステーションで通信を行うために は、それぞれのコンピュータを区別するためのアドレスが必要である。インター ネット上の(正確にはインターネットプロトコルで通信を行う)装置に割り当て られるアドレスをインターネットアドレス(IPアドレス)と言い ”172.、 24.4.1”のようにドットで区切られた4つの10進数で表される。 インターネットに接続される全ての装置にはユニークなIPアドレスが割り当 てられるようになっており、それらはすべてNIC(Network Information Center) で管理されている。そのなかでも、日本で使用されるIPアドレスはJPNIC で管理されている。 しかし、インターネットが急速に普及するにつれてIPアドレスの不足が心配 。 、 、 されるようになったきた そのため 組織内部だけのクローズなLAN環境では インターネットにアクセスする場合だけ本来のユニークなアドレス(グローバル アドレス)を割り当てる方法が利用されるようになった。 プライベートアドレス空間からグローバルアドレス空間(インターネット)を Network Address アクセスできるようにする仕組みとしては、プロキシやNAT( )が利用される。 Translator 5 クライアントサーバモデルのネットワークプログラミング クライアントサーバモデルはネットワークアプリケーションの形態の1つで、 1つのアプリケーションがクライアント サービスを要求するもの とサーバ サ( ) ( ービスを提供するもの)で構成されている。クライアントとサーバはネットワー ク上でお互いに通信を行いながら具体的な処理を行う。 、 、 一般的にサーバはクライアントからの要求を待ち 要求に対応した処理を行い その結果をクライアントへ送信する。たとえば、WWWはクライアントサーバモ デルのシステムであり、Netscape Navigator Internet Explorer、 などのクライアン トと、Apache Netscape Enterprise Server、 などのサーバがHTTPによる通信を 行っている。
本実験では、クライアントとサーバの2つのプログラムがネットワーク上でお 互いに通信を行いながら具体的な処理を行うプログラムを作成する。
6 ソケットインターフェース ソケットインターフェースは,トランスポート層とアプリケーション層の間の , インターフェースで,ユーザが作成するアプリケーション層のプログラムから トランスポート層のプロトコルモジュール(TCP,UDP) を呼び出すために使用さ れる。TCP かUDP どちらかを選択できるが,ここではUDP によるコネクショ ンレス型通信の基本的手順を説明する。ソケットインターフェースのシステムコ ールを使用する例を下図 に示す。プログラム内で呼ばれるシステムコールを説 明する。
client process server process
() () socket socket () () bind bind ・ ・ ・ ・ ・ request ・ () () sendto recvfrom () () recvfrom sendto ・ reply ・ ・ ・ ・ ・ () () close close () 1 socket クライアント,サーバともに通信の最初に呼び出すシステムコール。 通信のための通信ポートの作成,使用するプロトコルを設定。 () 2 bind 作成したソケットを識別するためのアドレスを与える。 () () 3 sendto , recvfrom , 。 通信相手のソケットアドレスを指定して メッセージの送受信を行う クライアントはsendto() で要求して,recvfrom()で受け取る。 () 4 close データ転送終了時にソケットをクローズする処理を行う。
7 ポート番号 ポート番号にはユーザが自由に使える物と,すでにきめられたサービスのため に割り当てられているものがあ る。以下に一般に割り当てられているポートの一覧を示す。 ポート番号 用途 ウェルノウンポート( , など良く使われるサービス用) 0 - 255 telnet ftp 予約済ポート(スーパーユーザプロセスのみ利用可能) 256 - 1023 自動割り当てポート 1024 - 5000 (ポートを指定しなかった場合に自動的にシステムが割り当てる) ユーザが自由に使えるポート 5001 - 65535 3 実験 週目は文字通信プログラムを作成する。通信で送られてきた 文字(半角英 1 ASCII 数字)を大文字にしてクライアントへ返信するサーバープログラムと,通信で文字を , , 送り また送られてきたデータを受信・表示するクライアントプログラムを使用して ソケット通信を学ぶ。
4 実験結果 < > #include stdio.h < > #include sys/types.h < > #include sys/socket.h < > #include netinet/in.h < > #include netdb.h #define MAXLINE 512 #define SERV_UDP_PORT 35567 /¥*穴埋め 使用するポート番号を定義する: */ #define Error fprintf
( )
main argc, argv int argc; char *argv ;[] {
int n, sockfd, servlen, dummylen; struct sockaddr_in serv_addr, cli_addr; struct hostent *host;
char *hname; char *program;
char sendline MAXLINE , recvline MAXLINE + 1 ;[ ] [ ] int errno; program = argv 0 ;[ ] ( ) { if argc == 1 fprintf stderr, "( 引数(サーバーホスト名) を指定してください.¥n" ;) exit 0 ;( ) } /* 穴埋め 引数で指定したサーバ情報を: host に代入する*/ (( ( [ ])) ) {
if host = gethostbyname argv 1 == NULL 5
fprintf stderr, "%s¥n", h_errno ;( ) exit 0 ;( )
}
/* serv_addr にサーバアドレスを設定する*/ bzero char * &serv_addr, sizeof serv_addr ;(( ) ( )) serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr inet_ntoa host- h_addr ;( ( > )) serv_addr.sin_port = htons SERV_UDP_PORT ;( )
exit 0 ;( ) }
/* cli_addrにローカルアドレスを設定する*/ bzero char * &cli_addr, sizeof cli_addr ;(( ) ( )) cli_addr.sin_family = AF_INET;
cli_addr.sin_addr.s_addr = htonl INADDR_ANY ;( ) cli_addr.sin_port = htons 0 ;( )
/* 穴埋め:bind() */
( ( ( ) ( )) ) {
if bind sockfd, struct sockaddr * &cli_addr, sizeof cli_addr == -1 fprintf stderr, "Bind Error: %d!¥n", errno ;( )
exit 0 ;( ) }
/* main loop */
printf "( 終了する場合は「Ctrl+D」を入力してください.¥n" ;)
( ( ) ( ) ) {
while printf "%%" ,fgets sendline, MAXLINE, stdin != NULL n = strlen sendline ;( )
/* 穴埋め ループ内の処理: */
if ((servlen = sendto sockfd, &sendline, n, 0, struct sockaddr * &serv_addr, sizeof( ( ) serv_addr == -1 fprintf stderr, "Send Message is failed!: %d¥n", errno ;
( ))) ) ( )
continue; }
if ( (recvfrom sockfd, &recvline, servlen, 0,( (struct sockaddr * &cli_addr,) )) ) {
&dummylen == -1
fprintf stderr, "Receive Message is failed!: %d¥n", errno ;( ) continue;
}
recvline n = 0;[ ] fputs recvline, stdout ;( ) } printf "( 終了します¥n" ;) close sockfd ;( ) exit 0 ;( ) } 入力した文字列がサーバに送られ、大文字になって帰ってくる様子を確認。
5 考察 UDP TCP 1 本実験では というコネクションレス型の通信プログラムを作成したが、 を利用してプログラムを作成する場合、どのような点が異なるか、2.2.2 の手順と 比較して具体的に説明せよ。 クライアント側 •
クライアント側では,socket ,connect ,write ,read ,close() () () () () の5 つのシ ステムコールを使用する.UDP とは違い,一度繋ぐと通信路を確保して接 bind 続をし続けるため,クライアント側に返すために宛先が必要ないため, () は存在しない.write()・read() はそれぞれ sendto()・recvfrom() に対応 しており,データの送信受信を行う.
サーバ側 •
socket ,bind ,listen ,accept ,write ,read ,close 7 サーバ側では, () () () () () () () の つのシステムコールを使用する.こちら側は相手から繋いでもらうためにソ ケットにアドレスを設定しないといけないため,bind()が存在する.listen() は接続待ち状態であり,クライアント側の connect() を待つ(また,接続さ れるクライアント数もここで設定する 3).accept() はクライアントから () されたときにその接続を受け,接続された場合にクライアント側 connect に通知する.write()・read() はクライアント側とデータの送受をするため の関数である.このように,TCP プロトコルを使った通信では,確実に相 手に情報を届けることができ,送ることができなかった場合もちゃんとエラ MSN TCP ーが返すことができるようになっている. メッセンジャーなどが で動いている例である. 2 本実験で作成したプログラムを,効率的なプログラム,他人から見て読みやすい プログラムに改良するとしたら どのような点が考えられるか検討せよ., プログラムの穴を埋めているときに気になったのが変数に注釈文がついていな いこと。変数を使おうと思ったときにどの変数を使って良いのか分からず、新し い変数を作ってしまった。これは明らかな無駄である。 宣言型 変数名; // 変数の使用目的 などの形にすれば改善は可能。 3 本実験を行って 難しかった点 興味を持った点などについて感想を述べよ。, , 穴埋めプログラムのはずが、変数宣言や、エラー処理などで穴埋めで無い部分 。 。 を加えすぎてしまったので組み直すことになってしまった 明らかな無駄である かといって1から組めるわけでもないので全部組めと言われても困るところがあ