Master Koala's pages

Month
Filter by post type
All posts

Text
Photo
Quote
Link
Chat
Audio
Video
Ask

November 2009

JUNET記念日
Path: titcca!nttlab!nttss3!nttspl!koala
From: koala@nttspl.ntt.JUNET (Master Koala)
Newsgroups: fj.jokes,fj.news.adm
Subject: Re: JUNET memorial day. (In KANJI)
Message-ID: <7041@nttspl.ntt.JUNET>
Date: 3 Jul 88 19:53:43 GMT
References: <7000@nttspl.ntt.JUNET>
Distribution: fj
Organization: NTT SEC Software Production System Division, Shinagawa
Lines: 31
Xref: titcca fj.jokes:1588 fj.news.adm:320

in article <7000@nttspl.ntt.JUNET>, koala@nttspl.ntt.JUNET (Master Koala) says:
> in article <1231@cskvax.csk.JUNET>, shige@cskvax.csk.JUNET (Shigeki Yoshida) says:
>> 
>>   7月1日はJUNET記念日です。常日頃、休みなく働いてくれている
>> inewsに感謝の意を表し、今日一日はポストを控えJUNETのあり
>> がたみを噛みしめましょう。
> 
>   でも、世の中には修正もれのシステムが残っていて、今ごろ慌てていたり
> して。(^O^)

と言って、人のことを心配していたら、

in article <211@nttss3.ntt.JUNET>, futagami@nttss3.ntt.JUNET (Toshitsugu Futagami) says:
> 
> ## inewsがDate:が評価できないと騒いでいるなあ。7月になって何かが
> ## おかしくなったかな?

という投稿があったので、「おかしいな」と思って調べたら、僕の大チョンボ
だいっ。

  nttss3にインストールする時に、Julyをjulyにしていない未パッチの原本を
持っていって、普通にpatchを動かしてしまったようです。そんなものだから、
7月の記事を見ると、

	inews: Unparsable date "3 Jul 88 16:19:11 GMT"

と言って騒いでいたようです。ほとんど冗談の世界ですね。ああ、恥しい。


		あんまり性能のよくないinstall屋さんだいっ、の
				コアラ大将だいっ
Nov 6, 2009
顔文字の歴史
From vn Wed Jan 13 13:19:20 1988
Subject: Many faces of Master Koala (Re: Swap region)
Newsgroups: fj.jokes
References: <637@rrlip.rrl.JUNET>
Distribution: fj

in article <637@rrlip.rrl.JUNET>, tori@rrlip.rrl.JUNET (Hiroshi Toriyama) says:

| (atr の某氏によると、仮想領域をパンクさせるようなものをワークステーション
|  に流すのが、そもそもの間違いだそうですが (^O^)  <- コアラの笑顔 )

  すいません。このアイデアいただきね。
  ついでに、いくつか付け加えます。

	(^O^)	コアラ大将の笑顔
	(-O-)	眠っているコアラ大将
	(*O*)	あきれてしまったコアラ大将
	(@O@)	横の方をそっと見ているコアラ大将
	(=O=)	薄目で見ているコアラ大将
	(>O<)	わあっと驚くコアラ大将
	(dOb)	普通のコアラ大将
(参考) http://staff.aist.go.jp/k.harigaya/doc/kao_his.html
            
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 16 )
     「コアラ大将のTCP/IP入門」
		    ( Part 16 )


お客さんH
 こんにちは。

コアラ
  あっ、お客さんだ。こんにちは。

お客さんH
 「コアラ大将のTCP/IP入門」は毎号欠かさず読んでいます。
大変ためになり、僕にもようやくソケットを使うプログラムが書け
そうです。大変感謝しています。

コアラ
  ええっ、本当ですか。嬉しいなあ。

お客さんH
 ところで、一つ細かい質問があるのですがよろしいでしょうか。

先輩
  どうぞ、御遠慮なく。僕で分かることでしたら。

お客さんH
 サーバの例題プログラムの中で、

>>		  if((asd=accept(sd,&from,&nbyte)) < 0){
>>			  if(errno != 14)
>>				  perror("serv: error");
>>			  continue;
>>		  }

という部分があるのですが、どうして errno が 14 の時は perror 
を呼ばれてないのですか。errno 14 は EFAULT で、マニュアルに
は、

     EFAULT      The addr parameter is not in a  writable
                 part of the user address space.

とありました。とくに perror していけない理由も思いつかないの
ですが。

コアラ
  そう言えばそうですねえ。おかしい。変ですね。

先輩
 ううむ、気付かれてしまいましたか。実はここは例題を出した時
には僕にも理解できなかった部分だったんですよ。ただ、こうして
おかないと、サーバから山のように14番のエラーが発生してしま
うので、どうしようもなくてこうしておいたんです。

お客さんH
 そうだったんですか。そうとは知らず、どうもすいません。

先輩
  最近、ようやく原因が分かりました。実は&nbyteはfromの中の有
効長を返してくれるパラメータなのですが、ただ単純な出力パラメー
タではないんですね。マニュアルを注意深く読んでやっと分かった
んですが、ここにはaccept呼び出し時にはfrom構造体ポインタが指
している領域の有効長を設定する必要があるんですよ。
  例題では、この初期値の設定がなかったんです。だから、14番
のエラーが頻発したわけなんです。初期値設定さえちゃんとしてお
けば14番のエラーが発生することはなく、特別扱いする必要もな
かったんです。

お客さんH
 そうなんですか。えっと、Sun のマニュアルを見るとー、

The addrlen is a value-result parameter; it should initially
contain the amount of space pointed to by addr; on return it
will contain the actual length (in bytes) of the address
returned.

うーん、確かに!  value-result parameter という語法があるの
ですね。

  int sd,asd,nbyte = sizeof from;

とでもしとけば良かったのですね。でも、例題のプログラムから

  if(errno != 14)

を省いただけのものでも、Sun3/260 OS 3.2 では問題なく動いたの
は単なる偶然だったのでしょうね。

先輩
  ほう、動きましたか。僕はSun-3/260 OS 3.5でやって動かなかっ
たように記憶していますが。

コアラ
  どちらにしろ、先輩ってかなりいい加減なんだなあ。あきれちゃ
うなあ。

先輩
  まあ、誰だって1回や2回の間違いはあるさ。

コアラ
  1回や、2回ぐらいしかないつもりですか?

先輩
  まあ、そう言うなよ。これでも頑張っているんだからね。Hさん、
今日はわざわざどうもありがとうございました。

お客さんH
 いろいろお忙しいでしょうが、これからも頑張って下さい。では、
失礼します。

コアラ
  気をつけて返って下さいね。時々、途中のsendmailがこけていま
すから、足元には十分注意して下さいね。
  ああ、行っちゃった。

先輩
  ううん、さすがだね。僕より詳しそうだ。

コアラ
  そりゃ、そうですよ。先輩とは格が違いますよ。


(つづく)


## さあ、この暑い最中、休みもせずに、勉強しましょうね。
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 15 )
     「コアラ大将のTCP/IP入門」
		    ( Part 15 )


端末
  ピピピー。メイル様の到着です。

コアラ
  お久しぶり。端末君。ええっと、なになに。最近ネットに入った
ばかりです。「TCP/IP入門」の噂はかねがね伺っていました。
バックナンバーを取り寄せて読ませてもらっていますが、面白いで
すねェ。これからも頑張って下さい。フムフム、そういうことですっ
て。

先輩
  僕の説明が分かりやすいということだな。

コアラ
  違いますよ。この方は「分かりやすい」とおっしゃってるんじゃ
なくて、「面白い」とおっしゃってるんですよ。これは、もう、僕
の明るい性格の反映ですよ。僕がいるから、この「TCP/IP入
門」がもっているんですよ。

先輩
  もう帰りたくなってきたなあ。

コアラ
  まあまあ、そんなにすねないで。脇役だって大切な仕事ですよ。

先輩
 じゃ、説明の続き。sendtoとrecvfromについては大体分かっても
らえたと思う。UDPではread/writeは使えないので、これらを使
うわけだね。

コアラ
  TCPと違って仮想回線として接続されるわけではないというこ
とでしたよね。

先輩
  そうだ。だけどサーバ・プロセスではbindを使って自分のソケッ
トの使うポート番号を指定することはできるんだ。

コアラ
  前から聞きたいと思ってたんですけど、TCPでもUDPでもポー
ト番号をbindできるのはサーバだけなんですか。クライアントの方
はbindできないんですか。

先輩
  ふむふむ。今までは説明を簡単にするために、そういうふうに言っ
てきたわけだけど、厳密に言えばクライアントだってbindでポート
番号を指定することはできるんだ。

コアラ
  でも、TCPの例題クライアントではbindは使いませんでしたね。

先輩
  そのとおり。本当はsocketでソケットを作った後でbindすること
はできたんだけど、簡単のために省略したんだね。だからconnectの
時にシステムが空いているポートを適当に割り付けてくれたわけな
んだ。

コアラ
  そうだったんですか。

先輩
  ポート番号は大きく2つに分けられているんだね。1つはシステ
ムで予約されている部分で小さい番号が与えられている。それ以外
は未予約の番号でユーザが自由に使うことができて、これには大き
な番号が与えられている。
 /etc/servicesには、このシステムで既に予約されている番号と
特定のサービス名の関係を記述してあるわけだ。だから、これらの
ポートを一般ユーザが自分のソケットにbindすることはできないん
だ。特権を持ったプログラムだけがこれらのポートに対してbindで
きるわけだね。もちろん、普通のプログラムがこれらのポートに対
しconnectすることは自由にできるんだよ。

コアラ
  ふうん。そうですか。つまり、rlogindとかtelnetdというような
サーバはrootから起動されないといけないわけなんですね。例題の
サーバもそうだったんですか。

先輩
  そうだね。例題の中ではtryという名前でbindしたと思うけど、こ
れに実際割り当てられている番号がシステム予約域に入っているか
いないかだね。入っていれば、サーバを起動する時にroot特権が必
要だね。

コアラ
  で、UDPではどうなっているんですか。

先輩
 そこで話が元へ戻るわけだが、UDPでもサーバは特定のポート
にbindしてソケットを使うことになるわけだ。また、サーバも相手
ポートにconnectすることができるんだ。

コアラ
 あれっ。UDPではコネクションの確立は必要ないということじゃ
なかったですか。

先輩
  ううん。このUDPのconnectはTCPにおける仮想回線の確立と
いうような感じではなくて、相手先のホスト番号やポート番号が一
定なら、それを予め設定しておくという感じだね。だから、connect
したくないならしなくてもいいよ。

コアラ
  複雑だなあ。

先輩
  原理自体はそんなに難しいわけじゃないから、1度自分で整理し
てみるといいと思うよ。案外、単純だと分かるからネ。


(つづく)


## 「励ましのメール」とか「質問のメール」待ってますからね。
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 14 )
     「コアラ大将のTCP/IP入門」
		    ( Part 14 )


コアラ
  えっ。じゃ、どうするんですか。

先輩
  どうしたんだい。突然、大きな声で叫んだりして。

コアラ
  いやだなあ。緊迫状態で前回から続いているんですけど。

先輩
  ああ、そうか。何だろうかと思ってしまったよ。話はUDPで使
うソケットではread/writeシステムコールが使えないというところ
までだったね。

コアラ
  あのう、前はREAD/WRITEと言っていませんでしたか?

先輩
 些細なことによく気付くね。その時の気分だよ。それより、話の
本筋に注意して、ちゃんと聞いてるんだよ。

コアラ
  はあい。

先輩
  とにかく、SOCK_DGRAMのソケットは通信相手とパケットの送受信
を行なう毎にそのアドレスを指定する必要があるんだ。そのために
準備されたのが、sendtoとrecvfromのシステムコールなんだ。ほら、
コアラ君、マニュアルでその形式を確認してごらん。

コアラ
  ええっと、sendtoはsendto(s, msg, len, flags, to, tolen)です
ね。recvfromはrecvfrom(s, buf, len, flags, from, fromlen)とい
うふうになっています。

先輩
  パラメータだけど、最初の3個はread/writeとよく似ている。第
1パラメータは使用するソケットディスクリプタ番号、2番目は送
受信バッファのアドレスを、3番目はバッファの大きさを指定する
んだ。

コアラ
  第4パラメータ以降がread/writeにはないものですね。

先輩
  そうだ。4番目のflagsはオプション的に使われるものだから、今
は0を指定しておく。5番目のパラメータが問題の相手先のアドレ
スだ。sendtoの時は送信先を指定し、recvfromの時は受信先のアド
レスがここに入って来る。第6パラメータは、第5パラメータの有
効長を送信時には指定し、受信時には設定されてくることになる。

コアラ
  あれっ、変だなあ。

先輩
  どうした、コアラ君。

コアラ
  recvfromのfromはプログラム側で設定するんじゃないんですか。

先輩
  いや、違う。パケット受信時に、システムが設定してくれるフィー
ルドだよ。

コアラ
  そうすると、同一マシン上に複数のUDPのソケットが受信状態
で待っている時は、そのマシンへ送られてきたパケットはどのソケッ
トで処理されるんですか。

先輩
  それを今から説明しようと思っていたんだ。まず復習だ。TCP
の時はどのようにしてポート番号を設定していたかな?

コアラ
  /etc/servicesを見てサーバは自分のサービスに対応するポート番
号を知り、bindしていました。クライアントもやはり/etc/services
を見てサーバのサービスに対応するポート番号を知り、connectして
いました。

先輩
  そうだ。サーバは自分のソケットに特定のポート番号を設定し、
そこへやってくるパケットを受信していたわけだ。クライアントは
サーバのソケットがどのポートを使っているかを調べ、そのポート
に対してパケットを送っていたわけだね。この時、サーバはどうやっ
てクライアントのポート番号を知ったのかな?

コアラ
  ううん、ええっと、わからない。

先輩
  それはね、クライアントからコネクションの確立要求のパケット
がやってきた時、そのパケットの中の発信元のアドレスを見て相手
が誰だかわかったんだ。

コアラ
  へえ。そうだったのか。でも、TCPの例題サーバでは相手が誰
だとかというデータは無かったような気がしますけど。

先輩
  acceptシステムコールの第2パラメータであるaddrにちゃんと入っ
ていたんだが、あの例題ではそれを全く利用しなかったね。

コアラ
  じゃ、TCPのサーバは相手が誰だか知らなくても通信はできた
んだ。

先輩
  そうだね。コネクションの確立はあくまでTCPプロトコルの中
で自動的に行なわれるからね。

コアラ
  UDPでは、どうなるわけですか。

先輩
  UDPにおけるサーバ・クライアントもそれによく似た感じで処
理が進むわけだね。

コアラ
  ふうん。


(つづく)


## ふう、話が難しいなあ。皆さん、分かりますか。もう少し質
## 問を多くしないといけないかなあ。(dOb)
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 13 )
     「コアラ大将のTCP/IP入門」
		    ( Part 13 )


先輩
 さて、話を続けようか。UDPの使い方の話だ。まず、socketを
作ることから始める。作り方はTCPの時と同じ感じだね。s=socket
(af, type, protocol)において、afにはAF_INETを指定し、typeには
SOCK_DGRAMを指定し、protocolには0を指定することが多いね。どう
だい、コアラ君、これらのパラメータの意味が想像できるかい。

コアラ
  afでの指定はARPAのInternet-addressを指定しているわけですよ
ね。これはAF_UNIXという指定では同一マシン上のプロセスとしか
通信できないのに対して、別々のマシンで動いているプロセス間で
も通信できるようにするための指定ですよね。

先輩
  そうだね。

コアラ
  typeはTCPの時にはSOCK_STREAMを指定したのに対して、UD
Pではこのように指定するわけなんでしょ。protocolが0なのはT
CPの時と同じですね。SOCK_DGRAMという種類のソケットはUDP
でしか利用できないから、0と指定するだけで十分なわけですね。

先輩
  そういうことだ。ここでDGRAMというのはdatagramのことで、通
信がコネクションの確立という状態にならずに行なわれる完全な信
頼性は満たしていない通信方式のことを言っているわけだね。それ
に対してSOCK_STREAMというのはパケットの順序がちゃんとしてい
て、十分にパケット転送の信頼性があり、双方向のコネクションが
確立した状態で行なわれる完全なバイトストリームを提供している
わけだね。

コアラ
  難しいなあ。言葉が難しすぎるんじゃないですか。

先輩
  そうかい。これでも随分と丁寧に説明しているつもりだけどねえ。
つまり、datagramというのはプログラムで指定したようにパケット
の発着信が行なわれるわけなんだ。だけど、前から言っているよう
に複雑にゲートウェイで接続されたIPネットワーク自体には、パ
ケットを正しく転送することを保証する機能は組み込まれていない
んだ。だから、発信されたパケットが相手に届いたかどうかチェッ
クするのは、その上位のプロトコルか、またはユーザプログラムの
責任になるわけだね。

コアラ
  そのあたりは何回も聞かされて、納得してます。

先輩
  だから、datagramとして発信したパケットが正しく相手に届いた
かどうかはユーザプログラムで責任を持たなければならないわけだ。
TCPプロトコルによって発信されたパケットは、TCPプロトコ
ルの機能の中でその到着が確認されるため、ユーザプログラムはT
CPを信じてしまえばいいわけだ。分かるかい。

コアラ
  はい。すると、僕みたいな初心者はTCPを使ったほうが安心で
すね。

先輩
  そうだね。安全と言えば安全だね。さて、UDPを使う場合でも
やはりサーバクライアントモデルでプログラムを作った方が分かり
易いんで、そういうふうに説明させてもらうよ。

コアラ
  いいですよ。

先輩
  TCPの時は、出来たソケットに対して、自分のポート番号をbind
して、listen状態にし、新しいソケットをacceptしたね。

コアラ
  はい。クライアントだと、相手のポート番号とIPアドレスを指
定してconnectしました。

先輩
  こういう処理がUDPのソケットには必要がないんだ。

コアラ
 connectionlessな通信だからですか?

先輩
  そうだよ。UDPのソケットは特定の相手ソケットと接続した状
態にする必要がないわけだ。逆に言えば、パケットを送りたい時に
相手ポートを指定してパケットを送信し、相手は相手で受取りたい
時に受取りポート番号を指定してパケットを受け取ればいいんだ。
そして、パケットを1個送受信したからと言って、次にまたそのソ
ケット間でパケットをやりとりしなくてはいけないなどという制約
なんかはないんだ。

コアラ
  へえ。1個のソケットでどこのマシンのどのポートとも通信がで
きるわけですね。

先輩
  やろうと思えば、そういうふうにもプログラムは書けるね。

コアラ
  で、やはり、このソケットに対してREAD/WRITEするわけですか。

先輩
  いや、違う。UDPのソケットではREAD/WRITEはできないんだ。

コアラ
  えっ。じゃ、どうするんですか。


(つづく)


## というわけで、緊迫の次号を待て。(^O^)。メールも待ってる
## からね。(メールが来ないと、話が進まなくって。)
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 12 )
     「コアラ大将のTCP/IP入門」
		    ( Part 12 )


先輩
  フム、だから、こうなるわけか。フムフム。

コアラ
 何してるんですか? あっ、何かデバッグしてる。何ですか、そ
れ?

先輩
  いいかげんな話をするなんて変な噂が流れないように、動作確認
をしてるんだよ。

コアラ
  へへえ、泥縄方式ですね。

先輩
  これも、皆、コアラ君のためにやっているわけだよ。少しは感謝
してくれないかなあ。

コアラ
  で、今から何の話をするんですか。

先輩
  TCPのソケットの使い方は簡単に説明したから、次はUDPの
説明をしようと思っている。

コアラ
  UDPですか。TCPとは、かなり違うんですか。

先輩
  違うと言えば違う。似ていると言えば似ている。

コアラ
  それじゃ、情報量はゼロじゃないですか。使われた文字サンたち
がかわいそうですよ。

先輩
  つまり、TCPでは特定の2つのプロセス間に仮想回線を接続し
て、その間の通信をソケットで行なったわけだね。さらにTCPは
パケットの到達を保証しないイーサネット上のIPプロトコルを使っ
て確実なデータ転送を行なうために、いろいろな制御情報をパケッ
トに載せていたわけだ。

コアラ
  データをwriteしたらパケットが飛んで、反対側でreadできると
いうわけではないんですか?

先輩
  基本的にはそうだけど、もし途中でパケットが紛失したり、破壊
されたりした時には、パケットの再送を行なわなければならないん
だ。また、パケットがどこかでひっかかってしまって到着が遅れる
と、後から再送されたパケットと二重に受け取られるかもしれない
しね。受取側では、どこまで正しく受け取れたかをいちいち送信側
に知らせる必要があるんだね。

コアラ
  面倒ですね、TCPって。

先輩
  いやいや、TCPを使うのは簡単なんだよ。そういう面倒な作業
は皆TCPプロトコルがやってくれるからね。

コアラ
  UDPはどうなんですか。

先輩
 UDPはそういう作業はほとんどやらないね。パケットは送りっ
ぱなし、受取りっぱなしだね。

コアラ
  パケットが届かなかったら?

先輩
  UDPは関知しないんだ。UDPプロトコルを使用しているプロ
グラムの責任で対処しなければならないね。

コアラ
  面倒ですね、UDPって。

先輩
  コアラ君にかかると何でも面倒になってしまうね。でもUDPを
使っているプログラムもかなりあるんだよ。rwhoやsyslogやtalkな
んかがそうだ。あとNFSもTCPではなくUDPを使っている。

コアラ
  ええっ、NFSもですか。ファイルの中味があちこち壊れるんじゃ
ないですか。ちょっと怖いなあ。

先輩
  まあ、NFSの場合は内部でちゃんとチェックしているから大丈
夫だよ。とにかく、TCPに比べてプロトコルが単純だから転送速
度が速いんだよ。

コアラ
  ふうん。まあ、そうでしょうね。

先輩
  まとめるとだね、UDPのソケットを作って通信を行なうことが
できて、そこではパケットは任意のUDPのソケットへ送れるとい
うこと。そして、パケット転送にエラーが発生してもUDPはそれ
に対する処理はしないということ。そのかわり、TCPに比べて速
いということ。これらがUDPの特徴と言えるね。

コアラ
  なかなか、ポイントを押さえたいい説明だね。

先輩
  こらっ、態度が悪いぞ。本当に、もう、コアラ君ときたら。

コアラ
  じゃ、次にUDPでのソケットの使い方の説明をしてもらおうか。

先輩
  おいおい。本当に、どうなってるんだい。


(つづく)


## 質問があったら、メール下さいね。たくさん集まるようだっ
## たら、前みたいに質問会を開きますからね。でも難し過ぎる
## のはダメだからね。(^O^)
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 11 )
     「コアラ大将のTCP/IP入門」
		    ( Part 11 )


お客さんA
 はじめまして。Aと言います。

コアラ
 こんにちは。僕、コアラ大将です。こっちが、僕の先輩です。

先輩
 はじめまして。

お客さんA
 この企画、いつも楽しみにしてるんですよ。fj.lecture が来て
いないか、日に3回ほど端末から rnと打ってしまうんですよ。今
ちょうどプロセス間通信のテストプログラムを作成しているんで、
大変役に立っています。早く話が次に進まないか心待ちにしてま
す。

コアラ
 へえ、そうですか。嬉しいなあ。

お客さんA
 まるで,連載ドラマを見ているようですね。お仕事がお忙しいこ
とと思いますが、これからもこの話に期待していますからね。

先輩
 はあ、これからもよろしくお願いしますね。

お客さんA
 ところで、1つ質問なんですが、クライアント側でソケットを作っ
て得たデイスクリプタをクライアント側でクローズしていますでしょ。
これをサーバー側ではできないのでしょうか?

先輩
 ほうほう。ええっとですね、ソケットというのはあくまで、ある
プロセスの中で定義されたディスクリプタの一種ですから、他のプ
ロセスからcloseすることはできませんねえ。でも、プロセス間の
コネクションを切断するという意味でしたら、それはどちらのプロ
セスからも出来ますね。それにはshutdown(2)というシステムコール
を使います。これによって通信路の切断要求のパケットが相手先へ
送られますからね。どう、コアラ君にも理解できたかな?

コアラ
 はい。connect(2)によって接続要求のパケットが出ていくのと対
象的な感じですね。

お客さんY
 こんにちは。これの愛読者です。といっても愛している読者では
ありませんよ。愛読しているものです。

コアラ
 わっ、ひょうきんなおにいさんだ。あっ、どうもはじめまして。

お客さんY
 質問があるんです。sockaddrに関してですが、

>	struct	sockaddr_in	sin;
>	struct	sockaddr	from;

ということですよね。でもman してみると、bind や connect のアー
ギュメントタイプは、sockaddr なんですけど、わざわざ sin を
sockaddr_in で宣言する理由は何ですか? lint をかけるとここの
ところでアーギュメントタイプに関して文句をいいますが。

コアラ
 えっ、そうなんですか。嫌だなあ、僕達にいい加減なことを教え
たりして。

先輩
 ちょっと待ってよね。おかしいなあ。あっ、本当だ。確かにそう
だね。ううむ。sys/socket.hにはsockaddrの定義しかないようだし。
sockaddr_inはどこで定義されていたかなあ。

コアラ
 ねえ、Yさん。案外、いい加減な人だってこと、わかりました。

先輩
 あった、あった。netinet/in.hにあるねえ。ということはつまり
ですねえ、sockaddrというのは一般的なアドレス指定であって、普
通僕達がTCP/IPで使うときはsockaddr_inというinternet形式を使っ
て指定するということになりますね。ちなみに、sockaddrは

struct sockaddr {
	u_short	sa_family;	/* address family */
	char	sa_data[14];	/* up to 14 bytes of direct address */
};

こういう形で、最初の2バイトで以下の14バイトの領域のアドレ
スデータがどういうプロトコルのものかを定義していて、残り14
バイトの表現については規定していませんね。つまり、TCP/IP以外
のアドレスでも指定できる可能性を残してあるわけですね。それに
対してsockaddr_inは

struct sockaddr_in {
	short	sin_family;
	u_short	sin_port;
	struct	in_addr sin_addr;
	char	sin_zero[8];
};
struct in_addr {
	union {
		struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
		struct { u_short s_w1,s_w2; } S_un_w;
		u_long S_addr;
	} S_un;

という構造体になっていて、14バイトの領域の先頭2バイトをポー
ト番号に、続く4バイトに32ビットのIPアドレスが入るという
ふうに決められているわけですよ。分かりますか。

コアラ
 その説明、今、考えついたばかりでしょ。本当に正しい答えなん
ですか。

先輩
 間違ってないと思うけどなあ。

お客さんY
 もう1つ質問があるんですけど。"try" に対するポート番号を
/etc/services に定義する必要が有ると思いますが、これは server
側と client 側の両方のマシンで同一である必要が有りますか?
また、この番号を勝手に決めてしまっていいのですか?

先輩
 これは同じでないといけません。仮にサーバがtryは5000番だと
思って待っているのに、クライアント側がtryは6000番だと思って
接続要求を出したら、接続ができませんからね。番号の決め方は、
今のところ、空いている番号を見つけて割り振るんだと理解してお
いて下さい。ただし、システムで0から1024なり2048なり
4096あたりまで予約されていて、一般ユーザには使えないこと
がありますから、注意して下さい。

お客さんY
 早くtcp/ip が理解できるようになりたいですねえ。

先輩
 頑張って下さいね。コアラ君もだよ。

コアラ
 はあい、わかりましたよ。

お客さんN
 始めまして、Nと申します。

コアラ
 はじめまして。コアラ大将でぇーす。

お客さんN
 このお話は、毎回楽しみにしています。ところで、

>> 先輩
>>   各種のサービスに割り当てられたポート番号を知るために、get-
>> servbynameという関数を使うんだ。この例では、tryという名前の
>> サービスに対応したポート番号が手に入るね。ほら、覚えているだ
>> ろう。rloginでは513/tcpと書いてあっただろう。同じように、try
>> についても/etc/servicesに定義してあるわけだけど、そこから情
>> 報を得るためにこうしているんだ。

僕のマシンの/etc/servicesには"try"が定義されてなく、ポート番
号を得られないんです。こういう時、getservbynameを使わずに空い
ているポート番号を教えてくれる関数があればいいのだけれど。man
rcmdにそれらしいことが書いてあったのですが、いまいちよくわか
らないんですけど。

先輩
 実は、このtryというのは前もって定義されているものではなく、
僕達の使っているマシンで勝手に定義したものなんです。通信実験
用の番号なんで、特定のサービスに結合しているわけではないんで
す。
 /etc/servicesは各マシンで勝手に書き換えるといろいろと問題が
発生します。ネットワークで結合されている場合、この情報がマシ
ンごとに違っていると大混乱が起きる恐れもあります。だから、特
定のサービスにポート番号を与える時は、ネットワーク全体のこと
を意識してやって下さいね。
 あと、クライアントが使うポート番号は、そのクライアントで特
定のサービスに使用されていないポートの中から適当なものを順次
選んで割り当てていきます。

コアラ
 その説明も今思いついたばかりのものですか。

先輩
 これは、単なる事実の解説だと言っていいと思うけど。まあ、僕
もTCP/IPのエキスパートじゃないから、分からないこともあ
るし、間違ったことも言うさ。それをコアラ君のようにいちいちあ
げられると、僕は困ってしまうんだけどね。

コアラ
 へへへ。いつも威張っているお返しですよっ。さて、次回は何の
話ですか。

先輩
 それは、次回のお楽しみさ。

コアラ
 まだ、考えていないんでしょ。分かってるんだから。


(つづく)


## 先輩がギャフンというような難しい質問を求めています。初
## 心者の方、頑張って質問して下さいね。徹底的にいじめて泣
## かせてしまいましょう。(^O^)
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 10 )
     「コアラ大将のTCP/IP入門」
		    ( Part 10 )


端末
 ピ、ピ、ピ。メールはありませんよ。

コアラ
 あれっ、残念だな。今回はなしか。まあ、いいや。前回たくさん
来たから。では、クライアントの説明、いきます。

#include	<errno.h>
#include	<stdio.h>
#include	<netdb.h>
#include	<sys/types.h>
#include	<sys/socket.h>
#include	<netinet/in.h>

コアラ
 これは、いつもの通りですね。

先輩
  そう、中に何が書いてあるかは、自分で見ておいてね。

main(argc,argv)
int	argc;
char	*argv[];
{
	struct	sockaddr_in	sin;
	struct	servent	*sp;
	struct	hostent	*hp;
	int	sd;
	char	line[128];

コアラ
 サーバには無かったhpというのがありますね。

先輩
 うん、そうだね。これは後で接続する相手ホストのIPアドレス
を調べるために使われるんだ。

	if((sp=getservbyname("try","tcp")) == NULL){
		fprintf(stderr,"error\n");
		exit(1);
	}
	if((hp=gethostbyname(argv[1])) == NULL){
		fprintf(stderr,"error\n");
		exit(2);
	}

コアラ
 getservbynameはサーバと同じ使い方ですね。gethostbynameとい
うのが新しく出てきましたけど、同じような感じですか。

先輩
 そうだね。このクライアントの第1パラメータは接続先のホスト
名を指定することになるけど、そのホスト名からIPアドレスを得
るのにこういう処理をしているわけだ。

コアラ
 これも、/etc/hostsから情報を得ているわけですか。

先輩
 そういうこと。getservbynameでも説明したけど、ネームサーバが
動いているときは、そちらから情報を得ることになる。ネットワー
クに数十台以上ホストがあると、/etc/hostsへの新しいホスト名の
登録作業も大変だからね。

	bzero((char *)&sin,sizeof(sin));
	bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
	sin.sin_family=hp->h_addrtype;
	sin.sin_port = sp->s_port;

コアラ
 これもサーバの処理とよく似ていますね。sinをクリアして、そこ
へいくつかのデータを代入していますね。

先輩
 hp->h_addrは相手ホストのアドレス、hp->h_lengthはその長さ、
hp->addrtypeはこれがアドレスの型を、つまりIPアドレス型だと
いうことを示しているわけだね。sp->s_portはポート番号だね。

	if((sd=socket(PF_INET,SOCK_STREAM,0)) < 0){
	       perror("error");
	       exit(3);
        }

コアラ
 sinの準備ができたところで、ソケットを作るわけですね。

	if(connect(sd, (char *)&sin, sizeof(sin)) < 0){
		perror("error");
		exit(4);
	}

コアラ
 そして、さっき準備したsinを使ってconnectするわけですね。

先輩
 その通り。前に説明したように、ここでサーバに向かって接続要
求のパケットが発信され、サーバからも確認と要求のパケットが来
るわけだね。

	read(sd,line,128);
	printf("Last message: %s\n",line);
	printf("Send message: ");
	gets(line);
	write(sd,line,128);
	close(sd);

	printf("OK\n");
}

コアラ
 クライアントでは、サーバから128バイトのメッセージを受信
して、それを標準出力に表示する。そして、標準入力からメッセー
ジをlineに得て、そのlineの領域128バイトをサーバへ送信する
ということですか。

先輩
 当たりだ。つまり、このクライアントを端末から起動すると、サー
バが保持していたメッセージがそこに表示される。そこで、端末か
ら1行入力すると、それが新しいメッセージとしてサーバに送られ
保持され、クライアントは終了するわけだね。

コアラ
 次に別のホストからクライアントを起動してサーバに接続すると、
そのメッセージが読めるわけですね。

先輩
 そうだよ。どうだい、簡単な例だけど、サーバ・クライアントが
どういうもので、どういうふうにプログラミングされているか、大
体分かったかな。

コアラ
 何となくは。でも、まだまだ分からないことがたくさんあるなあ。


(つづく)


## さあて、例題も片づき、次は何を勉強することになるのか、
## 楽しみだなあ。(^O^)
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 9 )
     「コアラ大将のTCP/IP入門」
		    ( Part 9 )


端末
 ぴ、ぴ、ぴ。メールの団体様がお着きになりましたあ。

コアラ
 わわわ。こんなにいっぱいメールがきちゃった。

先輩
 読んでいる人がいないんじゃないか、なんて言うからだよ。内容
はどんなだい?

コアラ
 あれは、失言でしたね。なになに。1日に3回くらいfj.lectures
を調べながら、記事の到着を待っています。わあ、こんなに熱心な
人がいるんですね。

先輩
 そうだよ。皆、コアラ君が一刻も早く、お利口さんになるのを待っ
ているんだ。さあ、そういうことだから続きを始めようか。

コアラ
 例題プログラムのサーバの途中からでしたよね。ええっと、たし
か、listenまで終ったんですよね。

	for(;;){
		char	line[128];

		if((asd=accept(sd,&from,&nbyte)) < 0){
			if(errno != 14)
				perror("serv: error");
			continue;
		}

コアラ
 このacceptによって、通信用のソケットが手に入るわけでしたよ
ね。

先輩
 そうだね。クライアントがconnectを実行することによって発信
される接続要求のパケットを、このacceptで受信し接続処理を行う
という感じだね。

コアラ
 この時は、クライアントからだけパケットが来るわけですか。

先輩
 実際には3個ぐらいパケットが飛ぶ感じだね。サーバーからも、
接続情報受領確認とクライアントへの接続要求のためのパケットが
発信され、最後にクライアントからその確認のパケットが発信され
るからね。だけど、今はそういうことは気にせずに、こう書けば通
信用のソケットが手に入ることだけを理解してくれたらいい。

		write(asd,line,128);
		read(asd,line,128);
		close(asd);
	}
}

コアラ
 この部分ですけど、前の話では実際の通信は子プロセスで行うと
いうことで、fork&execをするということだったと思いますけど。

先輩
 この例では、プログラムを簡単にしてサーバ自身が通信をしてい
るね。確かに、普通は子プロセスを作って通信と必要な処理をさせ、
親は直ちに別のクライアントからの接続要求を待つことが多いね。

コアラ
 そうですか。で、この部分はlineの内容を128バイト、クライ
アントへ送り、クライアントから128バイトのデータを受信して
lineに格納して、通信用のソケットを消去するわけですか。

先輩
 そうだ。つまり、このサーバは常時128バイトのメッセージを
保有していて、クライアントの要求があるとそれをクライアントへ
送信するわけだね。そして、替わりにそのクライアントから新しい
メッセージを送ってもらい、それをしっかり保持して次のクライア
ントからの要求を待つというサーバなんだね。

コアラ
 単純なサーバですね。

先輩
 ソケットに関する処理の概要を理解してもらうために、サーバ自
身の仕事は極力簡単にしたんだ。そういうわけで、サーバの基本的
な構造は分かってもらえたかな。

コアラ
 はい。ところで、このサーバは永遠に無限ループしているんです
か。

先輩
 そうだね。この例のサーバはいちいち終了することなく、次々と
クライアントの要求に応答していくわけだね。さて、次はクライア
ントの例を説明してもらおうか。


(つづく)


## たくさん来たメールの中には、難しい質問が書いてあったの
## もありました。難しい質問の答えには時間がかかるみたいで
## すよ。(^O^)
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 8 )
     「コアラ大将のTCP/IP入門」
		    ( Part 8 )


端末
 New mail for koala@nttspl has arrived:

コアラ
  おや、今回は英語で来たな。なになに。内容が無くても面白いの
に、内容がある。1記事で2度おいしい。わあっ、嬉しいですね、
喜ばれちゃった。僕のキャラクターがいいんですね、やっぱり。

先輩
  僕の教え方がいいんだよ。なにしろ、1言云えば、倍にして返す
コアラ君が相手だからね。さて、ところで、例題プログラムは理解
できたかな。

コアラ
  だめですよ。教えて貰っていないことがたくさん出てきているん
だもの。分かるわけないですよ。

先輩
  たくさんというわけじゃないだろう。少々はあるけどね。とにか
く説明してごらん。

コアラ
  ええっ、説明するんですか。参っちゃうよなあ。じゃ、サーバか
ら行きますっ。

#include	<errno.h>
#include	<stdio.h>
#include	<netdb.h>
#include	<sys/file.h>
#include	<sys/types.h>
#include	<sys/socket.h>
#include	<netinet/in.h>

コアラ
  ここはとにかく、これくらいincludeしておけばいいんでしょ。

先輩
  まあ、そういうことだね。

main(argc,argv)
int	argc;
char	*argv[];
{
	struct	sockaddr_in	sin;
	struct	sockaddr	from;
	struct	servent	*sp;
	struct	hostent	*hp;
	int	sd,asd,nbyte;

コアラ
 sinはbindで使う構造体ですよね。fromはacceptで使う構造体です
よね。sp、hpは何ですか、教わっていないんですけど。sd、asdはソ
ケットディスクリプタみたいですね。

先輩
  sp、hpについては、その次を読んでごらん。
  
	if((sp=getservbyname("try","tcp")) == NULL){
		fprintf(stderr,"error\n");
		exit(1);
	}

先輩
  各種のサービスに割り当てられたポート番号を知るために、get-
servbynameという関数を使うんだ。この例では、tryという名前の
サービスに対応したポート番号が手に入るね。ほら、覚えているだ
ろう。rloginでは513/tcpと書いてあっただろう。同じように、try
についても/etc/servicesに定義してあるわけだけど、そこから情
報を得るためにこうしているんだ。

コアラ
  何故、そんな面倒なことをするんですか。513なら513と書けばい
いのに。

先輩
  1つは将来の拡張に備えてだね。例えば/etc/passwdだって、直
接解析できなくはないけど、やはり、getpwentとかgetpwnamとかを
使うだろう。それともう1つ、本格的にLANが動き出せばネーム
サーバも使うようになるんだけどね、その時は、/etc/servicesで
はなくて、ネームサーバにこの種の情報を問い合わせにいくことに
なるんだ。getservbynameはそういう面倒もちゃんと見てくれるわ
けだね。

コアラ
  ネームサーバって何ですか?

先輩
  簡単に言えば、ネットワーク内で共通に使われる情報を一元的に
蓄積し、供給してくれるサーバだね。共通情報が各マシンに別々に
存在すると、情報の更新頻度によって、不一致が発生したりして不
便だし、更新作業もネットワークが大きくなればなるほど、大変だ
からね。

	bzero((char *)&sin,sizeof(sin));
	sin.sin_port = sp->s_port;

コアラ
  これは、sinの領域をクリアして、getservbynameで得たポート番
号をsin構造体に代入しているわけですね。

先輩
  そのとおり。後でbindで使うわけだ。

	if((sd=socket(PF_INET,SOCK_STREAM,0)) < 0){
	       perror("serv: error");
	       exit(2);
        }

コアラ
  これは習ったとおりで、ソケットを作っているんですね。

	if(bind(sd, (caddr_t)&sin, sizeof(sin)) < 0){
	       perror("serv: error");
	       exit(3);
        }

コアラ
  そして、さっき準備しておいたsinを使ってソケットにポート番号
をbindするわけですね。

	listen(sd,5);

コアラ
  そして、listenもこういうふうにして使うということですか。ふ
うん。これで、クライアントからの接続要求のパケットを受け取る
準備が完了したわけか。

先輩
  そう、さすがコアラ君だ。ちゃんとわかっているじゃないか。さ
て、次の無限ループではどうなるかな?


(つづく)


## ううむ、No.7の反応がイマイチだったなあ。やっぱり、読ん
## でる人は小数派なのかしら? (>O<)
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 7 )
     「コアラ大将のTCP/IP入門」
		    ( Part 7 )


先輩
 どうしたんだい、コアラ君。しょんぼりして。

コアラ
 僕、パパなしっ子になってしまった、、、。

先輩
 それは、お気の毒に。でも、いつまでも気落ちしてちゃいけない
なあ。元気を出して、勉強を続けようね。そうそう、いいものがあ
る。これを見て、元気を出すんだ。

コアラ
 何ですか?

先輩
 前から、コアラ君が見たがっていた、例題プログラムだ。さあ、
一気に行くよ。

/* 例題 始まり */

/* サーバ */

#include	<errno.h>
#include	<stdio.h>
#include	<netdb.h>
#include	<sys/file.h>
#include	<sys/types.h>
#include	<sys/socket.h>
#include	<netinet/in.h>

main(argc,argv)
int	argc;
char	*argv[];
{
	struct	sockaddr_in	sin;
	struct	sockaddr	from;
	struct	servent	*sp;
	struct	hostent	*hp;
	int	sd,asd,nbyte;

	if((sp=getservbyname("try","tcp")) == NULL){
		fprintf(stderr,"error\n");
		exit(1);
	}

	bzero((char *)&sin,sizeof(sin));
	sin.sin_port = sp->s_port;

	if((sd=socket(PF_INET,SOCK_STREAM,0)) < 0){
	       perror("serv: error");
	       exit(2);
        }

	if(bind(sd, (caddr_t)&sin, sizeof(sin)) < 0){
	       perror("serv: error");
	       exit(3);
        }

	listen(sd,5);

	for(;;){
		char	line[128];

		if((asd=accept(sd,&from,&nbyte)) < 0){
			if(errno != 14)
				perror("serv: error");
			continue;
		}
		write(asd,line,128);
		read(asd,line,128);
		close(asd);
	}
}

/* クライアント */

#include	<errno.h>
#include	<stdio.h>
#include	<netdb.h>
#include	<sys/types.h>
#include	<sys/socket.h>
#include	<netinet/in.h>

main(argc,argv)
int	argc;
char	*argv[];
{
	struct	sockaddr_in	sin;
	struct	servent	*sp;
	struct	hostent	*hp;
	int	sd;
	char	line[128];

	if((sp=getservbyname("try","tcp")) == NULL){
		fprintf(stderr,"error\n");
		exit(1);
	}
	if((hp=gethostbyname(argv[1])) == NULL){
		fprintf(stderr,"error\n");
		exit(2);
	}

	bzero((char *)&sin,sizeof(sin));
	bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
	sin.sin_family=hp->h_addrtype;
	sin.sin_port = sp->s_port;

	if((sd=socket(PF_INET,SOCK_STREAM,0)) < 0){
	       perror("error");
	       exit(3);
        }

	if(connect(sd, (char *)&sin, sizeof(sin)) < 0){
		perror("error");
		exit(4);
	}

	read(sd,line,128);
	printf("Last message: %s\n",line);
	printf("Send message: ");
	gets(line);
	write(sd,line,128);
	close(sd);

	printf("OK\n");
}

/* 例題 終わり */


コアラ
 こ、こんなものを見て元気を出せって言うんですか。どういう頭
の構造をしてるんですか。

先輩
 さあさあ、よく見て、よく見て。何をやっているプログラムか分
かるかな?


(つづく)


## 素人さんからの質問や励ましのメールが来ると、話が先へ進
## むみたいですよ。(^O^)
Nov 6, 2009
「コアラ大将のTCP/IP入門」( Part 6 )
     「コアラ大将のTCP/IP入門」
		    ( Part 6 )


端末
  ピピピのピ。コアラ君にメールだよ。

コアラ
  はいはい。話が段々難しくなってきましたが、これからも続けて
下さいね、ということみたい。

先輩
  ほらね。皆、ちゃんと勉強しているんだよ。コアラ君も頑張らな
くちゃね。さて、復習しようか。サーバが、TCPのコネクション
を確立するまでに発行するシステムコールを説明してごらん。コン
トロールLで待っててあげるからね。

コアラ
  わっ、いきなりコントロールLだなんて、びっくりするじゃない
ですか。
  ええっと、まず、
	s = socket(af, type, protocol)
でSOCK_STREAMのソケットを作るでしょ。それから、
	bind(s, name, namelen)
で、そのソケットにポート番号を割り当てる。そして、
	listen(s, backlog)
によって、クライアントからの接続要求を待って、
	ns = accept(s, addr, addrlen)
によって、特定のプロセスとの通信に使用する新しいソケットを手
に入れるんだという話だったと思います。

先輩
  おう、よく覚えたね。感心、感心。

コアラ
  えっへん、どんなもんだい。すごいでしょ。

先輩
  じゃ、次へ行くね。クライアントの方だ。これは簡単だよ。まず、
s = socket(af, type, protocol)でソケットを作るのは、同じだね。
その次にすることは、どのサーバに接続するかを指定することなん
だ。それにはconnect(s, name, namelen)というシステムコールを使
うんだ。nameはsockaddrという構造体を指すポインタで、namelenは
そのsizeofだね。

コアラ
  bindとどう違うんですか?

先輩
  bindはどういうポート番号を持つパケットを受け付けるかを指定
したんだけど、connectはどういうポート番号を与えてパケットを送
るかを指定することになるんだ。また、サーバがbind&listenしても
パケットは送出されないけど、クライアントがconnectするとパケッ
トが送出されるんだよ。

コアラ
  クライアントが送出する最初のパケットが接続を要求するパケッ
トなんですね。

先輩
  そうだよ。それを受け取ることによって、サーバ側のソケットは
コネクションを確立する手順を実行するわけだね。話が前後したけ
ど、connectのnameではsin_addrというフィールドに相手のIPアド
レスを、sin_portに相手のポート番号を代入するわけだね。

コアラ
  自分のアドレスやポート番号は代入しなくていいんですか?

先輩
  必要ないねえ。TCP/IPが送出パケットの中に自動的に代入してく
れるようになっているんだ。

コアラ
  クライアントのポート番号は、例えばrloginの時は513なんです
か?

先輩
  それは違うね。サーバは513を使うけど、クライアントはシステ
ムが自動的に割り当ててくれた番号を使うんだ。それぞれのUNIXシ
ステムで割当方法は若干異なるみたいだね。まあ、とにかく、その
ポート番号はあまり気にする必要はないからね。

コアラ
  で、connectが正常終了したらどうなるんですか?

先輩
  そのソケット s でサーバと通信ができるよ。

コアラ
  あれっ。通信用の新しいソケットは出来ないんですか?

先輩
  クライアント側はサーバ側とは違うんだ。元々のソケットで通信
ができるんだ。

コアラ
  どうなんですか。これで、read/writeしていいんですか?

先輩
  いいよ。随分待ちくたびれただろうけど、これでread/writeがで
きるようになったわけだ。

コアラ
  ふうむ、長い話だったなあ。

先輩
  じゃ、次は簡単な例を見せるから、これで今まで説明したことを
具体的に理解してくれるかな。

コアラ
  いいとも!!


(つづく)
Nov 5, 2009
「コアラ大将のTCP/IP入門」( Part 5 )
     「コアラ大将のTCP/IP入門」
		    ( Part 5 )


先輩
  さあ、コーヒーブレイクはおしまい。話を続けるよ。

コアラ
  ええっ。まだ、コーヒー飲んでないんですよ。

先輩
 何回も繰り返したけど、サーバ・クライアントのサーバの方から
考えるよ。
  サーバプロセスはクライアントからの接続要求を待って、そして
要求のあったクライアントプロセスとの間に仮想通信回線を確立す
るわけだね。そのために、サーバとクライアントの間で予め前もっ
て、そのサービスに使用する通信ポートの番号を決めておくんだ。

コアラ
  もう、話が始まったんですか。そうすると、サーバもクライアン
トも同じ番号のポートを使うんですか。

先輩
  決めるのは、サーバの使用するポート番号だよ。クライアントは
空いている適当なポート番号を使えばいい。
  このポート番号が/etc/servicesに書いてある情報だ。例えば、

	login           513/tcp

と書いてあるのは、rlogindの使うポート番号なんだけど、513番
だということだね。

コアラ
  tcpと書いてありますけど。

先輩
  TCPとUDPでは同じ番号を使うこともあるんだ。rlogindは
TCPの513番を使うわけだね。これはUDPの513番のポー
トとは無関係なんだ。
  というわけで、サーバは自分の受付用ポート番号を定義するのに
bind(s, name, namelen)というシステムコールを使うんだ。このname
はsockaddr_inという構造体を使い、そのsin_portというフィールド
にポート番号を代入するんだ。namelenはsockaddr_inの大きさを指
定することになる。

コアラ
 うう、わからない。具体的な例題はないんですか。

先輩
  例題プログラムはもう少し後にしよう。今は、とにかく、サーバ
はbindで自分のsocketにポート番号を与えるんだということを理解
してくれたらいい。
  さて、これでサーバはクライアントからの要求を待つことになる。
listen(s, backlog)を実行すればいいわけだ。このbacklogは接続を
待つクライアントのためのキューの数で普通5を指定する。

コアラ
  ということも、文句を言わずに覚えるだけですね。

先輩
  後で例題を見ながら、もう1度説明するからね。今は、そういう
ものかと思っていて欲しい。
  さて、クライアントから接続の要求が来たとする。すると、今ま
での「待機用」のsocketではなくて、特定のプロセスだけと通信で
きるsocketがaccept(s, addr, addrlen)というシステムコールによっ
て得られるんだ。

コアラ
  「待機用」と「通信用」ができるんですか。

先輩
 そうだよ。クライアントの要求を受け入れると、コネクションが
確立されて、そのコネクションに対して1個のsocketが出来るんだ。
このsocketは「待機用」のsocketと同じポート番号を持っているが、
ある特定のマシン上の特定のプロセスとの通信だけに使われるんだ。
元々の「待機用」のsocketは不特定のマシンの不特定のプロセスか
らの接続要求を再び待つことができるんだね。

コアラ
  サーバは忙しいですね、仕事がたくさんあって。

先輩
  だから、普通はacceptによって通信用の新しいsocketが得られた
ら、特定のプロセスとの通信は子プロセスに任せて、親プロセスは
新しい接続要求の監視に戻ることが多いね。

コアラ
  ふうん。ところで、acceptのパラメータのaddrとaddrlenは?

先輩
  これは、通信を要求してきたマシンのアドレスやポート番号が返
る領域だね。sockaddrという構造体のポインタと大きさを与えると
要求元の情報が返ってくる。

コアラ
  ふうん、はああ。

先輩
  どうした?

コアラ
  分かったような、分からないような。話の進み方が速いんだもの。

先輩
  ごめん、ごめん。ちょっと、用事があって急いだせいでもあるん
だ。次にクライアントの話をして、それからもう1度例題を見なが
らゆっくりサーバの説明をするからね。


(つづく)


## 素人さんの質問、歓迎します。(^O^)
Nov 5, 2009
「コアラ大将のTCP/IP入門」( Part 4 )
     「コアラ大将のTCP/IP入門」
		    ( Part 4 )


端末
 ピピピのピ。お手紙ですよ。

コアラ
 またまた、メールですね。しかし、この端末クン、回を経る毎に
ひょうきんになってくるなあ。

先輩
 今度のメールはどういう内容だい。

コアラ
 フムフム、進み具合いが速いのではないですか、っていうことで
す。三日坊主にならないで、ちゃんと勉強しましょうね、ですって。
ウウム、耳が痛いなあ。

先輩
 そうだね、継続こそチカラだからね。さて、話はどこまで進んだ
か、覚えているかい。

コアラ
 TCPプロトコルによるプロセス間通信のための仮想通信回線を
確立するために、s = socket(af, type, protocol)においてafには
AF_INET、typeにはSOCK_STREAM、protocolには0を指定してsocket
を作成する。

先輩
 オイオイ、教科書を棒読みしてるんじゃないのかい。正しいこと
は正しいけど、もっと分かりやすく易しく言い替えてごらん。

コアラ
 ううん、わかんない。だって難しいんだもの。

先輩
 あのね、つまりこうだ。イーサネットは物理的に1本の同軸ケー
ブルに各マシンから1個づつのトランシーバでインターフェースさ
れているね。この物理的に1個の装置を使って、マシン上の複数の
プロセスが他のプロセスに対して専用の通信経路を設定することを
TCPはサポートしてくれるわけなんだ。

コアラ
 ふうん、それをバーチャル・サーキットというんですね。

先輩
 そうだよ。ところで、話を先に進めようか。

コアラ
 そうしましょ、そうしましょ。ソケットを作ることから先に話が
進まないんだもの。早くプログラムを作りたいなあ。

先輩
 しようがないなあ。理解すべきことは順序立てて勉強しなくちゃ、
プログラムも作れないぞ。コアラ君。
 で、話に戻るけど、まず、サーバ・クライアント・モデルのサー
バの方から考えてみよう。

コアラ
 あの、何故、TCP/IPの話をすると、サーバ・クライアントの話に
なるんですか。例えば、who|wcみたいにパイプで結ばれたプロセス
のようなモデルの話はしてもらえないんですか。

先輩
 ううむ。するどく切り込んできたな。どう説明したら分かってく
れるかな。
 そう、考えてごらん。whoとwcはパイプで結ばれて、whoの標準出
力がwcの標準入力になるけど、その両者をパイプで結ぶ処理を実際
に行ったのは何かな?

コアラ
 シェルですか?

先輩
 そうだよ。whoとwcがパイプによって通信できるのは、シェルが
両者を接続してくれたからだよ。つまり、同一マシン上の親子関係
のあるプロセス間の通信を行うためにシェルが一種のサーバになっ
てセッティングをしてくれていると考えることができるね。
 ところが、異なるマシン間のプロセスを接続する作業を行うには
shやcshは使えない。エクスプリシットにサーバを定義する必要が
あるわけだ。

コアラ
 netshとかいうのを作ったらどうですか。

先輩
 たとえnetshを作っても、UNIXのプロセスはある1つのマシン上で
しか走行できないから、他のマシンのリソースを制御するには何ら
かのサーバの助けを必要とするだろうね。
 さて、話を元に戻すよ。socketシステムコールで作られたストリー
ム型のソケットを使ってサーバが通信の準備をする手順についてだ。

端末
 ピ、ピ、ピ。leaveで指定した時間ですよ。

コアラ
 やったあ。時間だ、時間だ。ひと休みしましょうよ。コーヒーブ
レイクだいっ。

先輩
 しようがないなあ。話が先に進まないじゃないか。


(つづく)


## ズブの素人の方の質問を御待ちしております。分かりにくかっ
## たら、言って下さいね。(^O^)
Nov 5, 2009
「コアラ大将のTCP/IP入門」( Part 3 )
     「コアラ大将のTCP/IP入門」
		    ( Part 3 )


端末
 ピ、ピ、ピ。新しいメールが届きました。

コアラ
 あっ、またメールだ。何々、TCP/IPを学ぶにはどうしたらいいの
でしょうか、ですって。

先輩
 ふむふむ。UNIXに関連する分野は皆そうなんだけど、初心者用の
参考書がないことが多いんだよね。最近は、一般コマンドやC言語
に関しては、日本語で書かれたとても良い本があるけど、少しつっ
こんで勉強しようとすると、ソースファイルを読むことになってし
まうね。TCP/IPやsocketに関しても、村井先生の本に少し概説が載っ
ているのと、UNIX MAGAZINEに時々解説が載るのを除くと、後は英語
かC言語で書かれたものしか、僕は知らないね。
 ということで、力と暇のある人はソースを読む、それが面倒な人
は知っている人に尋ねるしかないだろうと、僕は思うね。

コアラ
 そうすると、僕なんかは運のいいケースですね。幸せだなあ。

先輩
 ゴマをすっても手加減はしないからね。さて、socketシステムコー
ルの話をしているんだけど、どこまで話をしたっけ。

コアラ
 s = socket(af, type, protocol)を使うとソケットができるけど、
このままではread/writeはできない、Ethernet層やIP層のパケット
は宛先へ届く保証がない、IPアドレスは発信元や宛先を指定するの
に大切である、という話でした。

先輩
 おう、なかなかよく覚えているね。感心、感心。象印賞をあげよ
うね。

コアラ
 冗談はfj.jokesだけにして下さい。ここはfj.lecturesですよ。

先輩
 まいった、まいった。そこでsocketの話の続きなんだが、その前
に、サーバ・クライアント・モデルという話を一言で説明してしま
おう。
 プロセス間の通信にはいろいろな形態が考えられるけど、現在の
UNIXのTCP/IPではこのモデルを使った通信が多く採用されているん
だ。これは、socketによってある種のサービスを提供しているサー
バと、それに接続してサービスを受けるクライアントの両者間での
プロセス間通信なんだ。

コアラ
 rloginとかrshとかも、皆それだっていう話らしいですね。

先輩
 そうだよ。だから、コアラ君がrloginしたければ、コアラ君は
rloginコマンドを起動してsocketを作って、rloginのサーバにサー
ビスを要求すればいいんだ。それに対して、どこかでrloginのサー
ビスをしてくれるサーバが必要なんだよね。サーバがいなけりゃ、
コアラ君がrloginを起動してもどうにもならないんだよ。

コアラ
 そうなんですか。僕はrloginコマンドだけで、他のマシンにログ
インしているのかと思ってました。

先輩
 普通はシステム立ち上げ時に必要なサーバを起動しておくことに
なっているんだよ。
 さて、s = socket(af, type, protocol)に話を戻すよ。パラメー
タについて簡単に大胆に話をするよ。
 まず、af。これはsocketの利用範囲の定義だと思えばいい。AF_
UNIXだとそのマシン上のプロセス間だけで使えるし、AF_INETだと
IPネットワーク上の多くのマシン上のプロセス間で使えるんだ。

コアラ
 AF_INETでも同一マシン上のプロセスと通信出来るんですか。だと
するとAF_INETの方が便利でいいなあ。

先輩
 出来るよ。だけど、AF_INETで使用するときは二重定義にならない
ように、ちゃんと前もって計画しておく必要があるんだ。だけど、
今は話を単純にするために、AF_INETを使えば他のマシン上のプロセ
スと通信ができるというふうに覚えておいてね。
 次はtypeだ。これはsocketの機能みたいなものと思ってくれるか
な。TCP/IPではストリームとデータグラムが利用できる。データグ
ラムはUDPというプロトコルを使っていて、これはパケット到着の
保証がやはり無い。それに対して、ストリーム型はTCPプロトコル
を使っていて、これはパケットが相手先に必ず届くことを保証して
くれるプロトコルなんだ。というわけで、これはSOCK_STREAMを指定
する。
 最後はprotocol。これはtypeで指定した型が複数のプロトコルで
実現されているとき、そのプロトコルを指定するんだ。僕らがこれ
から勉強するSOCK_STREAMはTCPプロトコルでだけ実現されているか
ら指定する必要はないんだ。だから、0。

コアラ
 わあ、とうとうTCPの登場ですね。TCPというのはストリーム型を
サポートするプロトコルなんですね。ふうん、パケットはちゃんと
相手に届くんですね、良かった。これで、read/writeが出来るんで
すか。

先輩
 まだまだ。前にも言っただろう。s = socket(af, type, protocol)
だけではパケットの宛先や発信元の指定をしていないんだからね。
パラメータを指定してsocketが出来た、AF_INETでストリーム型、
TCP/IPプロトコルのsocketが出来た、というところまで話が終った
にすぎないんだよ。


(つづく)


## ズブの素人の方の質問をお待ちしております。(^O^)
Nov 5, 2009
「コアラ大将のTCP/IP入門」( Part 2 )
     「コアラ大将のTCP/IP入門」
		    ( Part 2 )


コアラ
 じゃ、login koalaと入力して、パスワードをヨイショっと。

端末
 ピ、ピ、ピ。

コアラ
 あっ、メールが来た。なになに、期待してます、頑張ってね。わ
あ、もうこんなメールが来ましたよ。

先輩
 こうなると、コアラ君も本腰を入れて勉強しないといけないね。
さてさて、man socketはもう読んだかい? 理解できたかな?

コアラ
 読んですぐ分かるくらいなら、質問に来たりしませんよ。何です
か、このs = socket(af, type, protocol)というのは。

先輩
 簡単に言えば、socketを実行するとディスクリプタsが返ってくる
ということだね。

コアラ
 ファイルや端末をオープンした時のディスクリプタと同じもので
すか。

先輩
 同じと言えば同じ、違うと言えば違うなあ。例えて言えば、tty
端末をopenして得られたfdは端末としてのioctlの対象になるけど、
一般ファイルをさすfdにはその種のioctlが効かないみたいにね。

コアラ
 この s を使ってread/writeやfgets/fputsは出来るんですか。出
来ないんですか。

先輩
 おうおう、いやにせっかちだね。簡単に言うと、この段階ではで
きないということになる。考えてごらん。socketのパラメータには
どのマシンのどのソケットと通信するかは指定していないんだよ。

コアラ
 そうか。じゃ、それを指定すればいいんですね。

先輩
 そんなに慌てないで、コアラ君。その前に理解しておくことはた
くさんあるんだから。
 まず、Ethernetについて一言。コアラ君も知っていると思うけど、
EthernetはCSMA/CDという方式をとっている。そして、それぞれの
インターフェースには6バイトのアドレスが付与されているんだ。

コアラ
 知ってます。CSMA/CDというのは任意のタイミングで同軸ケーブル
上へパケットを送出していいんでしょ。もし、衝突が起こってパケッ
ト送出が失敗したら、パケットをもう1度送出しなおすんでしょ。

先輩
 その通り。TCP/IPでは、このEthernetの上にIPというプロトコル
を載せている。このIP層では4バイトのアドレスで各マシンを区別
しているんだ。そして、このIPネットワークもEthernetと同様、パ
ケットが宛先へ届くという保証をしないんだ。

コアラ
 いやだな。どうして、そんな無責任なハードやプログラムを作る
んですか。

先輩
 それぞれのハードやソフトには、それぞれの役割があるんだ。そ
ういう保証をするのがTCPなんだよ。

コアラ
 ちょっと待って下さい。TCPとIPというのは一塊のプログラムじゃ
ないんですか。

先輩
 狭い意味では、TCPとIPはそれぞれ別のプロトコルなんだよ。こ
れ以外にUDPとかICMPとかのいろいろなプロトコルがあって、それら
ををまとめてTCP/IPと呼んでいるわけなんだ。

コアラ
 そうなんですか。ところで、プロトコルって実は何なんですか。
TCPはやたら複雑だとかいう噂を聞きますけど。

先輩
 コアラ君にもわかるように大胆に答えると、プロトコルの実体は
パケットのヘッダ形式と、制御情報授受の手順ということになるか
な。コアラ君に安心してもらうために、単純化して言えば、Ethernet、
IPではヘッダを正しく作れば、それで十分だと言える。TCPはヘッダ
を作る以外に、いくつかの特別な制御パケットを送る手順がある。
 だけど、プログラマがsocketシステムコールやその他の機能を使っ
てプログラミングしている限り、このようなプロトコルを陽に意識
する必要はあまりないと言っていいと思うよ。

コアラ
 良かった。簡単で。ところで、EthernetのアドレスとIPのアドレ
スというのは、どう違うんですか。

先輩
 socketを使ってプログラムを書く限りは、Ethernetのアドレスを
意識することはほとんどないと思うね。IP層でパケットが作られ、
Ethernet層に渡されるときに自動的に対応表からアドレスが選ばれ
ヘッダに埋め込まれるから、プログラマはEthernetアドレスは気に
しなくていいんだ。

コアラ
 へえ、本当に便利に出来ているんですね。なんだか、socketって
簡単なんだなあ。

先輩
 そうだよ。難しく考えることは、全くないんだよ。さて、s=socket
(af, type, protocol)の説明に戻ろうか。

(つづく)


## TCP/IP入門に関する質問はありませんか。メールを下
## さい。僕が代わって質問をしてあげます。ただし、質問はT
## CP/IPに関してズブの素人の人に限ります。(^O^)
Nov 5, 2009
「コアラ大将のTCP/IP入門」( Part 1 )
     「コアラ大将のTCP/IP入門」
		    ( Part 1 )


コアラ
 すいません。時間ありますか。教えて欲しいことがあるんですど。

先輩
 おや、コアラ君。何だい。

コアラ
 実はTCP/IPやソケットなんかのことを教えて欲しいんです。

先輩
 ほう、また、どうして、TCP/IPなんかを。

コアラ
 ええ、僕、nttsplのスーパーユーザーをやっているんですけど、
今まではイーサネットも接続されていなかったから、ネットワーク
の必要がなかったんです。それに、socket関連の部分のマニュアル
を読むと、難しいパラメータが並んでいたりして読む気がしなかっ
たんです。それに、試しにsocketを使ってみようと思っても、root
の特権がないとできないでしょう。そうすると、試すのもおっくう
だったんです。
 でも、このごろはSunやNewsなんかが出てきて、場合によっては
誰でもrootになれるし、ワークステーション間の通信も日常茶飯事
になってきたでしょう。僕も、もうそろそろ勉強しておかなきゃ、
世間から取り残されそうな気がしたものですから。

先輩
 そうだね。プログラミングができなくてもシステム管理はできる
かもしれないけど、知っていた方がより適切な判断ができるだろう
しね。今まではTCP/IPやsocketインターフェースはLANを
持っている先進的な組織の人たちだけのものだったけど、最近はイー
サネットを見たことがないという人の方が少なくなってきているよ
うだからね。

コアラ
 そうなんです。で、早速なんですけど、socketって本当は一体何
なんですか。

先輩
 おっ、素早い質問攻撃が始まったね。それも一言では答えられな
いような大きな問題だね。
 さて、最初にことわっておくけど、僕もそんなに詳しいわけでは
ないから、間違ったことを言うかもしれないし、コアラ君のような
初心者に説明するのに、若干省略的な説明になって正確性を欠いた
りするかもしれないから、最初からそのつもりで聞いててね。

コアラ
 はい、わかりました。あくまで、僕のような初心者に対する概要
説明だということですよね。

先輩
 そういうこと。で、socketというのは何かということなんだけど、
これは他の計算機のプロセスと通信を行うためにファイルディスク
リプタを拡張したものという考えで理解することが出来るんだよね。
 ファイルディスクリプタについては知っているね。openシステム
コールを実行すると帰ってくるfdのことなんだけどね。

コアラ
 はい、知っています。そうか、やっぱりファイルディスクリプタ
なんですか。UNIXではディスク上のファイルだけでなく、/dev
ディレクトリの下に定義された、各種の端末や、MTやメモリなん
かもopenして、一般のファイルと同じようにread,writeできるんで
すよね。

先輩
 そのとおり。UNIXはファイルもデバイスもパイプも全てこの
fdを使ってアクセスできるように統一してあるんだよね。だから、
他の計算機との通信も、このfdを使ってできるように設計されたん
だろうね。考え方はシンプルで美しいね。

コアラ
 でも、最近はセマフォとかメッセージキューとかいうのもあるそ
うですよ。

先輩
 その話は、いつか別の機会にしようね。コアラ君。

コアラ
 はあい。ところで、pipeとsocketはどういうふうに違うんですか。

先輩
 パイプは、同一のマシン上で動く親子関係のあるプロセス間でし
か使えないんだよね。ソケットは、同一マシン上でも、違うマシン
上でも、親子関係があろうとなかろうと、使えるんだよね。
 そうそう、4.2BSDではパイプはソケットを使って実現されている
んだよね。

コアラ
 じゃ、ソケットはパイプと上位互換性を持っているわけですか。

先輩
 ううむ、単純に上位互換性があるという言い方はしにくいなあ。
でも、パイプではできないプロセス間の通信を実現するために拡張
された概念だということはできるだろうね。わかるかい。

コアラ
 わかったような、わからないような。

先輩
 じゃ、具体的にソケットに関連するシステムコールについて見て
みようか。観点を変えると理解できるかもしれないしね。

コアラ
 はい、じゃ、ログインしてmanコマンドを投入しますね。

(つづく)
Nov 5, 2009
test

test

Nov 5, 2009
Next page →
2009
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December