|
>>1615 mak(spriggan)氏 > 0〜64までをチェックしかselectはチェックしていなかったので > selectはタイムアウトを返し、実際取得したファイルディスクリプタは > 64を超えた数になっていたのでFD_ISSETは反応を返した。 > というふうになっていた模様です。 確かになりますね。 知りませんでした。 しかし、fd_setの戻り値をチェックするのは、select(2)が正数を返した時のみにしておいた方が安全でしょう(select(2)に正しい第1引数を渡したとしても、タイムアウト時にfd_setがゼロクリアされるかは分かりません。規格としてゼロクリアが決まっているならO.K.でしょうが、そこまでしてselect(2)の戻り値のチェックを省く理由も見付かりません)。 # 今回はselect(2)の戻り値チェックを省いたおかげで、第1引数のバグに気づいたわけですが。 > ちなみに、ファイルディスクリプタの番号を > ここからここまでの番号しか取得しない。とか制限かける方法とか > ないのでしょうか? select(2)を呼ぶ時に、チェックすべきファイルディスクリプタの部分だけ、fd_setにマスクをかけますが(第1引数は効率の為)。 それとも、効率を気にしていますか? 確かに、非常に大きな番号のファイルディスクリプタ1つだけをチェックするとなると、無駄がありそうなことは否定しません。 それが気になるなら、poll(2)でしょうか。 |
|
>>1612 YAGI氏 # その場に行けば解決できるかもしれませんが、このやりとりでは、助けられる自信はありません。申し訳ないです。 > 当人まだ、知識が乏しく本にsmitとsmittyが書いてあったりもするのですが > 区別が分からずsmitでやってました^^; X以外でsmitを起動すると、tty版のsmittyと同じ動きなので、 > なお、smitのコマンド類はWinNTのTera Termより発行しています。 smitでもsmittyでも変わりありません。 # という事は、走る男を見ていないんですねえ。 # もしかして一度も見たことが無い、とかだったら不幸です。 > 私も、その手順で実際に行なってバージョンアップしたClientをもう一度 > NISの再設定を行ってServerのマップをmakeし直すと > 接続できなくなってしまうのです。 うーむ、あまり他人の文章のケチをつけるのもなんですが、何をどういう順序でやったのか、いまいち不明です。 (改行の位置に読点があると考えてよいのでしょうか。 この手の説明は、時系列に並べた箇条書の方が分かりやすいと思います。) |
|
>>1607 H.Motoki > コマンド型ツールでメール層送受信が可能なもの > かつ、添付ファイルが遅れるもの > かつ、Solarisで動作するもの 僕は知りませんが、 http://www.freebsd.org/cgi/ports.cgi?query=mime&stype=all&release=4.1-STABLE%2Fi386 の中を見ると、お望みのものっぽいのがありますので、 Solaris でコンパイルしてみてはどうでしょう。 >>1615 mak(spriggan) > selectはタイムアウトを返し、実際取得したファイルディスクリプタは > 64を超えた数になっていたのでFD_ISSETは反応を返した。 なるほど納得です。 > ちなみに、ファイルディスクリプタの番号を > ここからここまでの番号しか取得しない。 ここから、は指定できません。ここまで、ってのは select の 第一引数ですね。多くの UNIX の実装では select が扱えるのは 1024 までのディスクリプタのようですから、この程度なら 僕はあまり気にしません。あと、FreeBSD 4.2-RELEAE の select(2) には For historical reasons, select() will always examine the first 256 descriptors. とありますので、あまり神経質になるほどのことでもないかも しれません (し、そうでないかもしれません)。 |
|
繁盛しているのはいいけれど、返事が大変だなぁ。 >>1616 みかん(perlでソケットの質問してた方) >> select に <> や read を使うのは不適切です。 > 「クライアントやサーバーとうまく接続できたかどうかを確認する」、 > というような形が正しいselectの > 使われ方だと考えてもいいですか? いいえ。タイムアウトも select の正しい使い方です。 サンプルプログラムを書いてみました。 http://X68000.startshop.co.jp/~68user/tmp/select-sysread.pl echo サーバと echo クライアントです。2つスクリプトを書くのが 面倒だったので、fork して 片方が echo サーバになり、もう片方は echo クライアントとして動作するようにしました。 echo クライアントは echo サーバに接続し、文字列を送り、 それを受け取るだけです。echo サーバは select でソケットを 監視し、マルチスレッドサーバとして動作します。また、 クライアントが接続してから2秒経過したらタイムアウトとして 切断します。 で、これを動かすと、 親:5000 でクライアント待ち 子:localhost:5000 に接続します。 親:127.0.0.1:1291 からの接続を受け付け 子:送信メッセージ: HELLO (*1) 親:127.0.0.1:1291 に反応あり 親:127.0.0.1:1291 からメッセージ受信:HELLO 親:127.0.0.1:1291 へメッセージ送信:Received HELLO 子:受信メッセージ: Received HELLO (*2) 子:5秒眠ります (*3) 親:タイムアウトにより 127.0.0.1:1291 を切断 (*4) 子:新しい接続 (*5) 親:127.0.0.1:1292 からの接続を受け付け 子:送信メッセージ: HELLO AGAIN (*6) 親:127.0.0.1:1292 に反応あり 子:5秒眠ります (*7) となります。 最初は子が親に HELLO と送り (*1)、Received HELLO を受け 取ります (*2)。次に、子は5秒 sleep するので (*3)、親は タイムアウトとして切断します (*4)。 次に、子は新しいソケットを生成し再度親に接続します (*5)。 子は親に HELLO AGAIN と送ります (*6)。ただし、今度は メッセージの最後に改行コードを付けません。そして子は5秒 sleep します (*7)。するとここで親も子も動作が止まり、 永遠にデッドロックします。 なぜなら、親は子からのメッセージを $recv_message = <$sock>; で読んでいるからです。改行コードが送られてこないと、 ここでブロックしてしまいますので、これでは select を 使う意味がありません。 今回は意図的に改行コードを含まない文字列を送りました。 これと同じことが、改行コード以前のデータが到着している けれど、改行コードはパケットロスにより再送中、という 状況でも起こります。 というわけで、こういうときは sysread($sock, $recv_message, 100); などとします。これなら、既に到着しているデータのみを 読みます。100バイト分のデータを読もうとしますが、もし そのとき10バイト分のデータしか届いていなかったら、 そこで sysread から処理が戻り、select まで処理が 進み、正常にタイムアウト処理が行えます。 |
|
>>1613 ゆっきー > もし、入力した数値を計算し、結果を出力するような > サンプルを置いてあるページについて何か思い当たる > 点があれば教えていただけないでしょうか。 たとえばどのような計算をしたいのですか? テキストボックス1とテキストボックス2に数字を入力させ、 ボタンを押すと、2値の和を表示する CGI プログラムは 書けますか? >>1599 キチキチ そんな腐れサーバとは早く縁を切りましょう :-) > TELNETが禁止のサーバで、CRONTABみたいに定期的に > パールスクリプト実行できるテクニックってありますか? crontab 自体の使用が禁止されておらず、なおかつサーバ管理者を 敵にまわしてよいなら、CGI プログラムから crontab を設定する とか、~/.forward に crontab を設定するように仕込んでおいて メールを投げるなどの方法はあります。でも、お薦めしません。 あと、外部から定期的に指定の URL にアクセスしてくれる サービスがありますので、それを使って CGI プログラムを 一定時間ごとにアクセスさせるってのもあります。 確か webtimer って言ったかな。検索して探してみてください。 |
|
>>1610 rosegarden 補足などしてみたり。間違ってたらご指摘お願いします。 % cat と実行して、C-p,C-m,C-v,C-m とタイプしてみて下さい。C-p は ^P と 出力されるでしょう。rosegarden さんが書かれた通り、C-m は改行に なります。C-v C-m は ^M と表示されます。 この表示は、キー入力を受け取った端末ドライバが行っています。その 端末ドライバのキー割り当てを変えるのが stty コマンドなわけです。 改行 (この場合 C-m と等価) を打たない限りは、cat に文字列は 渡りません。1行のデータが確定して初めて、端末ドライバが cat に データを送ります。 次に tcsh か bash を起動して、そこで C-p,C-m,C-v,C-m をタイプして 下さい。C-m や C-v C-m はさきほどと同じですが (tcsh ^M でなくて ^J となりますが、両方改行コードなのでこれは置いといて) 、C-p の 挙動が違いますね。1つヒストリをさかのぼります。つまり、1行を 入力していなくても、1文字打った瞬間に tcsh や bash にデータが 渡っていることになります。 これは tcsh や bash が端末ドライバを経由せずに、直接キー入力を 取得しているからです。これを canonical モードといいます。端末の中で 動く mule や emacs や vi もcanonical モードになっているわけです。 これらは端末ドライバを経由していないので、stty の設定とは無関係です。 例えば tcsh のコマンドラインで C-v C-m で ^M となるのは、 % stty erase ^H しているからでなく、デフォルトで % bindkey ^V quoted-insert という設定になっているからです (bindkey は tcsh の内部コマンド)。 一方、伝統的な sh は canonical モードでは動きません。(Linux だと sh=bash だから例外)。つまり端末ドライバ経由でキー入力を拾う わけで、この場合は stty を使って設定します。 > du や df コマンドの -h (human friedly) オプション > というのはご存知でしょうか? 関係ないですが、FreeBSD 2.2.6-RELEASE では du -s が使えず くやしい思いをしました。 使いこなせると幸せだと思うオプション。 ls -lt、uniq -c、tail -f、du -s # du -s は Solaris にはないかな。 |