68user's page 掲示板

Prev< No. 3331〜3343> Next  [最新発言に戻る] [過去ログ一覧]
No. 3331 # lopper [E-mail] 2003/09/12 (金) 18:51:13
こんにちは、今Perl で UDP 通信を行うスクリプトを作っているの
ですが、少し分からないところがあるので質問させてください。

普通に UDP 通信は問題なく行えているのですが、送信元の IP アドレスが
拾えなくて悩んでおります。
recv 関数の戻り値で「送信元のアドレス」は拾えるのですが、送信元が
「どこへ宛てて送信したか?」が分からないのです。
IO::Socket::INET モジュールを使用していますが、peeraddr メソッドを
使っても何も返ってきません。

http://x68000.startshop.co.jp/~68user/net/udp-3.html に UDP で
connect 出来ると書かれていますが、connect すれば送信先アドレスを
拾う事ができますでしょうか?

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

No. 3332 # 68user 2003/09/13 (土) 01:35:39
>>3329 tomtom
> クライアントが受信待ちの状態の時に、サーバにソケットを
> クローズされたら、クライアントは、どうなるのでしょうか?
単に相手がソケットをクローズしただけなら、recv は 0 を
返します。

もし
      A が listen → B が connect → A がソケットクローズ
      → B が send → B が recv
なら、B は SIGPIPE を受けます。


>>3331 lopper
> recv 関数の戻り値で「送信元のアドレス」は拾える
> のですが、送信元が「どこへ宛てて送信したか?」が
> 分からないのです。
ソケットが送信先を記憶していないからです。同じ相手に
連続して UDP データグラムを送信する場合、
    socket(SOCKET, PF_INET, SOCK_DGRAM, 0);
    send(SOCKET, "hoge1", 0, $sock_addr);
    send(SOCKET, "hoge2", 0, $sock_addr);
と、毎回 send の引数に宛先である $sock_addr を指定
しなければいけません。なぜなら、一度目の send を
実行した後、SOCKET は $sock_addr に送信したことを
覚えていないからです。

# ソケットの先のアドレスが確定していないので、相手側で
# エラーがあって ICMP メッセージが返ってきても、カーネルは
# どのソケットにエラーを伝えればよいかわからない。だから
# 非 connect な UDP では相手側のエラーを拾えないわけです。

> connect すれば送信先アドレスを拾う事ができますでしょうか?
できます。
    socket(SOCKET, PF_INET, SOCK_DGRAM, 0);
    connect(SOCKET, $sock_addr);
この処理で SOCKET は「宛先が $sock_addr であること」を
覚えます。よって、この後 send する場合は
    send(SOCKET, "hoge1", 0);
と宛先を省略できるのです。

C で言うと、connect(2) することで、sendto(2) ではなく
send(2) が使えるということです。

No. 3333 # lopper [E-mail] 2003/09/13 (土) 22:21:38
68user さん、お返事ありがとうございます。
socket => connect を行う事で send を呼ぶ時に IP アドレスを
指定しなくても良くなるわけですね。

逆に recv などで受信する時はどうなのでしょうか。
例えば 192.168.0.255 宛のブロードキャストメッセージを受信しても
受信側からはブロードキャストメッセージを受信したのか、ユニキャストを
受信したのか分かりません。
Java などで UDP を使う時は相手が送信した IP アドレスと相手の IP
アドレス両方が分かるようですが、Perl では難しいのでしょうか?

No. 3334 # 68user 2003/09/13 (土) 22:25:12
ちょっと前にこのページが移転するかもと言っていましたが、
継続して使わせていただけることになりました。

68user's page は
      Startshop さん http://www.startshop.co.jp/
      両毛インターネットさん http://www.takauji.or.jp/
      Netboy さん
のご厚意により、回線・マシンを無料で使用させていただいて
おります。ここに改めて感謝の意を表したいと思います。

No. 3335 # 68user 2003/09/13 (土) 23:01:58
>>3333 lopper
> 例えば 192.168.0.255 宛のブロードキャストメッセージを受信しても
> 受信側からはブロードキャストメッセージを受信したのか、ユニキャストを
> 受信したのか分かりません。
一般的な BSD ソケットの API を使う以上は判断できないと思っています。

> Java などで UDP を使う時は相手が送信した IP アドレスと相手の IP
> アドレス両方が分かるようですが、Perl では難しいのでしょうか?
Java なら受け取ったデータグラムがブロードキャスト宛かどうかを
判断できるのでしょうか。

もしそうなら、Java が BSD ソケット API を使用せずネットワーク
機能を自前で作っているとは考えづらいので、BSD ソケット API で
実現可能なのだろうと思います。

DatagramSocket や DatagramPacket を見る限りでは、Java であっても
無理ではないかと思いましたが、もし可能なのであれば Java で記述
したサンプルプログラムを見せていただけますでしょうか。

No. 3336 # へにか 2003/09/13 (土) 23:07:33
おお、それはすばらしいですね。
もし私が両毛地方とか県南・県央(一部重複してますが)に住むことに
なったら、率先して両毛インターネットさんを選びたいという気持ち
でいっぱいです。

No. 3337 # lopper [E-mail] 2003/09/14 (日) 00:31:47
お返事ありがとうございます。
確実に Java で宛て先アドレスを取得できるという確認はしていない
のですが、以下の IP Messenger for Java の中では行っている
ようです。

http://www1.ttv.ne.jp/~digitune/Java/IPMsg/
からソースコードをダウンロードして、その中にある IPMProxyEvent.java
ファイルの中にある、getToIPMAddress で見ている見たいです。

P.S.
私は Java には詳しくはないので、確実かどうかわかりません。

No. 3338 # 68user 2003/09/14 (日) 01:12:32
>>3336 へにか
> 率先して両毛インターネットさんを選びたいという気持ちでいっぱいです。
本当に一銭たりともお金を払っていないので申し訳ないことです。
機会があればぜひとも。

>>3337 lopper
> IPMProxyEvent.java ファイルの中にある、getToIPMAddress で
> 見ている見たいです。
ぱっと見、Java 版 IP Messenger 独自機能である proxy 機能の
ソースのように見えます。README には「proxy 機能は TCP で実装
されている」とありましたので、多分違うのではないかと思います。

ちなみに 本家 IP Messenger は、受けたメッセージがブロード
キャストだと、ログに「(多)」などと表示されます。

しかしこれは UDP のレイヤで判別しているのではなくて、IP
Messenger のアプリで使用するコマンドの IPMSG_BROADCASTOPT が
立っているかどうかで判断しています。

No. 3339 # lopper [E-mail] 2003/09/14 (日) 03:13:58
lopper です。
お返事ありがとうございます。
ブロードキャストの件了解しました。なるほど Java版 ではプロキシに TCP を
使用しているので IP アドレスが拾えるのですね。わかりました。

色々とありがとうございました。自分なりに他の道を探してみます。

No. 3340 # tomtom 2003/09/15 (月) 09:10:42
tomtomです。
68userさん、お返事ありがとうございます。
そうですか、、もし、undefを返すなら以前の
説明がつくと思ったのですが、どうやら見当違い
のようですね。
また、色々考えてみる事にします。
原因が分かったら、また書き込みさせていただきます。

No. 3341 # のぐけん。 2003/09/15 (月) 12:15:50
こんにちわ。以前質問させてもらった者です。

それで、また質問なのですが(笑
Perlカテゴリの中のProxy Serverのことで質問です。
SIGPIPEシグナルが飛んで来た時用
ということで、$SIG{PIPE}を作られていますが、
これはどこで使用されているのでしょうか?
作っとけば勝手にってことなのでしょうか?

お忙しいかと思いますが、よろしくお願いします。

No. 3342 # 68user 2003/09/16 (火) 02:54:15
>>3341 のぐけん。
> $SIG{PIPE}を作られていますが、これはどこで使用
> されているのでしょうか? 作っとけば勝手にって
> ことなのでしょうか?
勝手に使用されます。

シグナルを最初に受けるのはカーネルです。カーネルは
プロセスごとに「SIGINT がきたらどーする、SIGPIPE が
きたらこーする」というテーブルを参照し、適切な動作を
行います。

つまり %SIG の書き換えというのは、自分のプロセスの
シグナル処理用テーブルを更新なわけで。

No. 3343 # 68user 2003/09/16 (火) 02:55:24
ところで、
    http://x68000.startshop.co.jp/~68user/net/link-book.html#8
の「UNIX ネットワークベストプログラミング入門」ですが、
    UNIX ネットワークプログラミング入門
        http://www.gihyo.co.jp/books/syoseki.php/4-7741-1754-4
として新版が出版されてるのを見付けました。

買ってませんが、立ち読みした限りでは htons は使われて
いました (笑)。大幅な内容追加というわけではないようなので、
「ベスト」の方を持っている人は不要かなーという感じです。

クライアントとサーバ両方を自作してみるというのは重要な
ことだと思いますので、改めてお勧めしておきます。

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