68user's page 掲示板

Prev< No. 1389〜1394> Next  [最新発言に戻る] [過去ログ一覧]
No. 1389 # Yuuki [E-mail] 2000/11/20 (月) 06:40:09
http://x68000.startshop.co.jp/~68user/net/sample/echo-server-1.c
このコードのバグを見つけました。
コンパイルして動かすとacceptで失敗するのでこっちの設定が
悪いんだろうと思ってFreeBSD関連のメーリングリストを
検索していたら原因がわかりました。
connected_socket = accept(listening_socket....
の上に
len = sizeof( sin );
が必要です。
バグの理由は
http://home.jp.FreeBSD.ORG/cgi-bin/showmail/FreeBSD-users-jp/43141
です。

No. 1390 # hemo [URL] 2000/11/20 (月) 19:05:25
はじめまして。
No.1389の指摘のついでですが

len = sizeof(peer_sin);

は、いらなんじゃないですか?
バグの理由でも書かれてるとおり
acceptの第3引数は、入出力両用ですので
帰ってきた値をそのまま使うのが正しいと思うのですけど。

No. 1391 # 68user 2000/11/20 (月) 20:11:38
> len = sizeof( sin );
> が必要です。
なるほど、確かに FreeBSD 4.2-BETA で動かすと accept に
失敗していました。これまではたまたま動いていたわけですね。
修正しておきます。ありがとうございます。

> len = sizeof(peer_sin);
> は、いらなんじゃないですか?
こっちの getpeername のは必要だと思います。以下 getpeername(2) より。
      Getpeername() returns the name of the peer connected to socket s.
      The namelen parameter should be initialized to indicate the amount
      of space pointed to by name. On return it contains the actual size
      of the name returned (in bytes). The name is truncated if the
      buffer provided is too small.


> これだとrenameするときに衝突する可能性ありますよね?
えっと、あの例では rename は使っていません。あの後 排他処理に
ついて書くつもりでしたが、時間がなくて全く手を付けていません。

> うまくrename時の衝突を回避する方法があればご教授ください。
もし rename でやるとしても、それ以前に複数のプロセスが
tmp_file へ同時に出力しようとする可能性があるので、あの
部分全体を排他する必要があります。

で、方法ですが、適当なロックファイルを用意して排他処理を
行えばよいです。flock でも symlink でも mkdir でも rename でも
何を使っても構いません。

No. 1392 # ぷに辻 2000/11/20 (月) 22:58:33
返事どうもありがとうです。

> えっと、あの例では rename は使っていません。

よく見てませんでした。申し訳ないです。。

> もし rename でやるとしても、それ以前に複数のプロセスが
> tmp_file へ同時に出力しようとする可能性があるので、あの
> 部分全体を排他する必要があります。

なるほど。そこで、お教えいただいた通りにちょっと改造してみました。

# 毎回違う名前で作る
$tmp_file = 'bbs'.$$.'.tmp';

open(TMP_OUT,"> $tmp_file");
print TMP_OUT "発言者: $from<BR>\n";
print TMP_OUT "$now_date $host<BR>\n";
print TMP_OUT "$message<HR>\n";

open(IN,"$data_file");
while (<IN>){
    print TMP_OUT $_;
}
close(IN);
close(TMP_OUT);

# tmp_file の内容を $data_file にコピーするだけ
#open(TMP_IN,"tmp_file");
#open(OUT,"> $data_file");
#while (<TMP_IN>){
# print OUT $_;
#}
#close(TMP_IN);
#close(OUT);

# コピーのかわりに、$data_fileにrename
# その前に排他処理。
$lock_file = 'bbs.lock';
touch($lock_file);
open(IN,"$lock_file");
flock(IN, 2);
rename($tmp_file, $data_file);
close(IN);
unlink($lock_file); # 必要ない??

これで完璧ですか??
読みこみ専用でオープンしてるのにflock()のオペレーションが「2」って
どうなんですかね。ちゃんと書きこみモードでオープンしなきゃだめですか??
改善点があればご教授くださいませ。
長文すみませんでした。

No. 1393 # hemo [URL] 2000/11/21 (火) 08:01:23
>> len = sizeof(peer_sin);
>> は、いらなんじゃないですか?
>こっちの getpeername のは必要だと思います。以下 getpeername(2) より。

失礼しましたぁ。。勘違いです。
きっちりしたサイズを指定しなくてもよかったんですね。
小さい場合は切り詰めるって仕様も最初は意味不明でしたが、
よく考えると最低でもアドレスファリは所得できそうなので有用ですね♪

No. 1394 # ふくし [E-mail] 2000/11/21 (火) 18:00:08
いつもすいません、ふくしです。
LDAP の使い方でこんなことができるかどうかどなたか相談に乗ってください。

Microsoft Exchange Server のアドレス帳で、集団のアドレス
(営業部 <markettng@nantoka.org とか)があって、
そこに送るとたくさんのひとに
(yamada.tarou@nantoka.org、satou.hanako@nantoka.net、、)に
行くようになっているとき、組織名を渡してこの構成員一覧を返す
アプリケーションを作ろうと思っています。

Exchange は LDAP を受け付けるときいたので、
Perl に Net::LDAP をインストールして、
サンプルをいじって使ってみたのですが、
marketting というメール アドレスが「ある」ことはわかるところまで
いったのですが、その内容まではわかりません。

ご存じの方がいらっしゃいましたら、よろしくお願いします。

Prev< No. 1389〜1394> Next  [最新発言に戻る] [過去ログ一覧]